No artigo anterior , escrevi sobre como adicionar enums no PHP8.1. A votação foi bem sucedida, pelo que a questão pode ser considerada encerrada.
No entanto, essa implementação de enums é apenas parte do plano global . Hoje vamos considerar o próximo item, sindicatos marcados, em russo que se traduz como "soma-tipo".
Ainda não foi votado , mas é proposto incluí-lo no PHP 8.1 também.
Todos esses termos "tipos de dados algébricos", "tipo de soma" parecem assustadores, mas na realidade tudo é bastante simples.
Por que tudo isso é necessário?
Resultado como em ferrugem
Se você escreveu em Rust, provavelmente encontrou o enum interno Result. Em Rust, Go, etc. não há mecanismo de exceção, pois essas linguagens consideram o tratamento explícito de erros muito mais confiável. A linguagem força você a trabalhar explicitamente todas as variantes de eventos, e não lançar uma exceção na esperança de que alguém no topo saiba sobre isso e saiba como lidar com isso corretamente. (Não vamos culpar aqui, no tópico de exceções vs tipos de retorno, todo mundo tem sua própria opinião). Falando especificamente sobre Rust, o resultado de uma chamada de função que pode gerar um erro geralmente é transformado em um valor Result.
O resultado consiste em duas variantes (casos na terminologia enum do PHP): Ok e Err. Poderíamos fazer variações usando a funcionalidade de enum anterior ou mesmo constantes, mas também precisamos retornar os próprios valores. Além disso, em caso de sucesso, o valor pode ser uma string e, em caso de erro, algum outro tipo. Por exemplo, inteiro (status de resposta HTTP).
Como ficará em PHP se a votação for bem-sucedida:
enum Result {
case Ok(public string $json);
case Err(public int $httpStatus);
}
function requestApi($url): Result {
//
}
agora podemos transferir essa resposta para outro lugar, e o conhecimento sobre o erro e seu tipo nunca será perdido.
Como escrevi no artigo anterior , enum é essencialmente uma classe, pode ter métodos etc. No caso de uma soma de tipo, os métodos podem ser gerais para o enum inteiro ou para um caso específico.
Aqui está um exemplo de implementação de Maybe monad (exemplo de RFC):
The Maybe Monad
(Em Rust, este tipo é chamado de Opção)
enum Maybe {
// This is a Unit Case.
case None {
public function bind(callable $f)
{
return $this;
}
};
// This is a Tagged Case.
case Some(private mixed $value) {
// Note that the return type can be the Enum itself, thus restricting the return
// value to one of the enumerated types.
public function bind(callable $f): Maybe
{
// $f is supposed to return a Maybe itself.
return $f($this->value);
}
};
// This method is available on both None and Some.
public function value(): mixed {
if ($this instanceof None) {
throw new Exception();
}
return $this->val;
}
}
, : Some None, Some , None — None. bind. value()
RFC ,
$a = Maybe::Some("blabla");
// $a = Maybe::None
$a->bind();
, - Result Maybe , - . pattern matching, RFC, . , :
$result = requestApi($url);
if ($result is Result::Some {%$json}) {
// $json
}
if ($result is Result::Err {%$httpStatus}) {
// $httpStatus
}
, match.
, tagged unions. , - , , tokenizer (scanner), . : , enum. , , , . . :
enum Token {
case Comma;
case LeftBrace;
case RightBrace;
case StringLiteral(public string $str);
case Identifier(public string $identifier);
// ..
}
?
, RFC , , . , "" . tagged unions, , pattern matching.
Se você estiver interessado em artigos semelhantes sobre desenvolvimento, em particular, o que acontecerá a seguir com o padrão de correspondência, assine o canal de telegramas Cross Join !