ti-enxame.com

Por que F #, Rust e outros usam o tipo de opção em vez de tipos anuláveis ​​como C # 8 ou TypeScript?

O tipo AFAIK, Option terá sobrecarga de tempo de execução, enquanto os tipos anuláveis ​​não, porque Option time é um enum (consumindo memória).

Por que não apenas marcar referências opcionais como opcionais, o compilador pode seguir a execução do código e encontrar sempre que não puder mais ser null?

Editar: Vejo que fui mal interpretado. Entendo e concordo com as vantagens de evitar ponteiros nulos. Não estou falando de ponteiros arbitrários que aceitam null. Estou apenas perguntando por que não usar metadados em tempo de compilação, como os tipos de referência anuláveis ​​do C # 8 e o TypeScript com verificações nulas rigorosas, onde os ponteiros padrão não podem ser nulos e há uma sintaxe especial (principalmente ?) para indicar um ponteiro que pode aceitar nulo.

Editar 2:

Além disso, Some é estranho, na minha opinião. Conversão implícita seria melhor. Mas que um recurso de linguagem e não relevante.

71
Chayim Friedman

Ponteiros anuláveis ​​/ não nulos têm semânticas muito complicadas.

Digamos que a função f receba um ponteiro anulável como argumento e deseje passá-lo para uma função g que tenha um ponteiro não nulo. Obviamente, apenas se o ponteiro não for nulo. Então g(p) gera um erro de tempo de compilação. E quanto a "se (p! = Nulo) g (p)"? Isso deve funcionar, mas qual é a diferença? P ainda é um Portanto, precisamos que o compilador seja inteligente o suficiente para saber que, após a instrução if, p não pode ser nulo.Portanto, você faz grandes alterações no compilador ou o recurso é inútil.

Agora pegue opcionais no Swift. Como eles são criados?

Primeiro, há um recurso muito geral e muito útil no Swift: enumerações com valores associados. Isso significa que, para cada caso de um enum, o programador pode definir quais valores são armazenados no valor de enum para esse caso. Esse recurso é usado para implementar opcionais: opcionais são apenas enumerações com dois casos "none" e "some", em que o caso "none" não possui dados associados e o caso "some" possui. Os opcionais nem fazem parte do idioma, eles são implementados na biblioteca padrão.

E quanto a "nulo"? nil é um literal, semelhante ao literal numérico ou de string. Portanto, nada é implementado no compilador. nil é traduzido para um "NilConvertibleLiteral" (provavelmente estou escrevendo isso errado). Na biblioteca padrão, onde Optionals são implementados, o operador de atribuição e os operadores de igualdade/desigualdade são sobrecarregados para o caso em que um operando é um "NilConvertibleLiteral", portanto opcional == nil é implementado como "o caso opcional é" none ". implementado na Biblioteca Padrão, exceto pelo pequeno detalhe no compilador que sabe compilar "zero", assim como sabe compilar "13" ou "3.1415e-20". E as comparações são definidas na biblioteca padrão para todos combinações de opcionais e não opcionais: opcionais nulos são iguais a opcionais nulos e não são iguais a opcionais não nulos, e dois opcionais não nulos comparam seus valores Nada aqui no compilador.

Existem dois pedaços de açúcar sintático: primeiro, o? e! operadores. Declarando uma variável como T? ou T! o torna opcional T. T? .x retorna x se T não for nulo e nil se T for nulo. T! .X retorna x se T não for nulo e é garantido para travar se T for nulo. No exemplo acima, "g (p)" não seria compilado porque você não pode usar um opcional onde um não opcional é necessário, "g (p!)" Seria compilado e travaria se p for nulo ", se p ! = nil {g (p!)} não pode falhar.

O outro pedaço de açúcar sintático faz toda a diferença: "se deixe x = expressão {...} else {...}. Expressão deve ser um valor opcional. Se não for nulo, o valor não opcional será extraído. e atribuído a x, e a primeira lista de instruções é executada; se a expressão for nula, a segunda lista de instruções é executada (opcional), combinando a verificação se um opcional é nulo com a criação de um valor não opcional.

As vantagens para ponteiros nulos e não nulos: 1. Pode ser usado para tudo. Como uma função que converte uma string em um número inteiro, retorna um Int opcional, então você escreve "if let i = Int (string) {sucesso} outro {falha} e não pode evitar o teste. 2. Ele possui um método muito limpo. 3. Não é possível evitar testes nulos, a menos que você use!, o que pode levar a uma falha garantida (e! significa que você está solicitando) 4. Na verdade, você não pode executar testes nulos. para valores não opcionais. Convertendo Objective-C para Swift Encontrei muitos testes paranóicos nulos apenas desaparecendo.

0
gnasher729