What does &. quer dizer em Ruby?

Encontrei esta linha de código ruby. O que significa isto?

@object&.method
Author: Santhosh, 2016-04-23

3 answers

Chama-se Operador de navegação seguro. Introduzido no Ruby 2.3.0, permite-lhe invocar métodos em objectos sem se preocupar que o objecto possa ser nil (evitando um erro undefined method for nil:NilClass), semelhante ao try Método nos carris. Para que possas escrever.
@person&.spouse&.name

Em vez de

@person.spouse.name if @person && @person.spouse

Dos documentos :

my_object.my_method

Isto envia a mensagem my_method para my_object. As o objecto pode ser um receptor, mas dependendo do método visibilidade enviar uma mensagem pode criar um Nometoderror.

Pode usar &. para designar um receptor, então my_method não é invocado e o resultado é zero quando o receptor é nulo. Nesse caso, o argumentos de my_method não são avaliados.

 122
Author: Santhosh, 2018-04-14 11:13:10

Nota: mesmo que @Santosh tenha dado uma resposta clara e completa, eu gostaria de adicionar um pouco mais de fundo e adicionar uma nota importante sobre o seu uso com variáveis não-instância.


Chama-se " operador de navegação seguro" (t. c. p." operador de cadeia opcional"," operador de cadeia condicional nulo", etc.). Matz parece chamá-lo de "operador solitário". Foi introduzido em Ruby 2.3 . Ele envia um método para um objeto apenas se não for nil.

Exemplo:

# Call method `.profile` on `user` only if `user` is not `nil`
@user&.profile

# Equivalent to
unless @user.nil?
  @user.profile
end

"Caixa de bordo" com variáveis locais:

Por favor, note que acima o código usa variáveis de instância. Se quiser usar um operador de navegação seguro com variáveis locais, terá de verificar se as suas variáveis locais são definidas primeiro.

# `user` local variable is not defined previous
user&.profile

# This code would throw the following error:
NameError: undefined local variable or method `user' for main:Object

Para corrigir esta questão, verifique se a sua variável local está definida em primeiro lugar ou coloque-a a zero:

# Option 1: Check the variable is defined
if defined?(user)
  user&.profile
end

# Option 2: Define your local variable. Example, set it to nil
user = nil
user&.profile     # Works and does not throw any errors

Método de fundo

Os carris têm um método que basicamente faz o mesmo. Usa send método interno para chamar um método. Matz sugeriu que é lento e este deve ser um recurso de linguagem embutido.

Muitas outras linguagens de programação têm características semelhantes: Objective C, Swift, Python, Scala, CoffeeScript, etc. No entanto, uma sintaxe comum é ?. (Ponto de interrogação). Mas, esta sintaxe não poderia ser adotada por Ruby. Porque ? foi permitido em nomes de métodos e assim, ?. a sequência de símbolos já é um código Ruby válido. Por exemplo:

2.even?.class  # => TrueClass
Isso é ... porque é que a comunidade Ruby teve de criar uma sintaxe diferente. Foi uma discussão ativa e diferentes opções foram consideradas (.?, ?, &&, etc.). Aqui está uma lista de algumas considerações:
u.?profile.?thumbnails
u\profile\thumbnails
u!profile!thumbnails
u ? .profile ? .thumbnails
u && .profile && .thumbnails

# And finally
u&.profile&.thumbnails

Ao escolher a sintaxe, os desenvolvedores olharam para diferentes casos de borda e a discussão é bastante útil para passar. Se quiser passar por todas as variantes e matizes do operador, por favor veja esta discussão de introdução de funcionalidades no Localizador de edição Ruby oficial.

 41
Author: Uzbekjon, 2017-07-25 19:21:41
Cuidado! Embora o operador de navegação seguro é conveniente, também pode ser fácil de enganar-se para mudar a sua lógica com ele. Eu recomendo evitar o uso dele no controle de fluxo. Exemplo:
str = nil

puts "Hello" if str.nil? || str.empty?
# The above line is different than the below line
puts "Hello" if str&.empty?

No primeiro exemplo, str.nil? devolve verdadeiro e str.empty? nunca é chamado, fazendo com que a instrução puts seja executada. No segundo exemplo, porém, str&.empty? devolve zero, o que é falso, e a declaração puts nunca é executada.

 3
Author: Thomas Deranek, 2018-06-28 21:04:29