248 votes

Que fait &. (esperluette) signifie en Ruby?

Je suis tombé sur cette ligne de code ruby. Que signifie `` moyenne en cela ?

324voto

Santosh Points 6791

Il est appelé la Sécurité de la Navigation de l'Opérateur. Introduit en Ruby 2.3.0, il vous permet d'appeler des méthodes sur des objets sans se soucier que l'objet peut être nil(en Évitant undefined method for nil:NilClass d'erreur), similaire à l' try méthode dans les Rails.

Vous pouvez donc écrire

@person&.spouse&.name

au lieu de

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

À partir de la Docs:

my_object.my_method

Cela envoie le my_method message à my_object. Tout l'objet peut être un récepteur, mais selon la méthode de la visibilité l'envoi d'un message peut soulever une NoMethodError.

Vous pouvez utiliser &. pour désigner un récepteur, puis my_method n'est pas appelé et le résultat est nul lorsque le récepteur est nul. Dans ce cas, l' les arguments de my_method ne sont pas évalués.

86voto

Uzbekjon Points 822

Remarque: Même si @Santosh a donné une claire et complète réponse, je voudrais ajouter un peu plus de fond et d'ajouter une remarque importante concernant son utilisation avec les variables d'instance.


Il est appelé "la Sécurité de la Navigation de l'Opérateur" (aka "Option de chaînage de l'opérateur", "Null-opérateur conditionnel", etc.). Matz semble l'appeler "solitaire" d'opérateur. Il a été introduit en Ruby 2.3. Il envoie une méthode à un objet que s'il n'est pas nil.

Exemple:

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

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

"Cas limite" avec des variables locales:

Veuillez noter que le code ci-dessus utilise les variables d'instance. Si vous souhaitez utiliser la sécurité de la navigation de l'opérateur avec des variables locales, vous devrez vérifier que vos variables locales sont tout d'abord définies.

# `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

Pour résoudre ce problème, vérifiez si votre variable est définie en premier ou le mettre à néant:

# 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éthode d'arrière-plan

Rails a try méthode qui fait fondamentalement la même. Il utilise send méthode interne pour appeler une méthode. Matz a suggéré qu'il est lent et cela devrait être intégré dans le langage.

De nombreux autres langages de programmation ont des caractéristiques similaires: Objective-C, Swift, Python, Scala, CoffeeScript, etc. Cependant, une syntaxe commune est - ?. (question de point). Mais, cette syntaxe ne peut être adopté par Ruby. Parce qu' ? a été autorisé dans les noms de méthode et donc, ?. symbole de la séquence est déjà valable du code Ruby. Par exemple:

2.even?.class  # => TrueClass

C'est pourquoi la communauté Ruby dû venir avec une syntaxe différente. C'était une discussion active et les différentes options ont été envisagées (.?, ?, &&, etc.). Voici une liste de quelques considérations:

u.?profile.?thumbnails
u\profile\thumbnails
u!profile!thumbnails
u ? .profile ? .thumbnails
u && .profile && .thumbnails

# And finally
u&.profile&.thumbnails

Lors du choix de la syntaxe, les développeurs ont étudié différents cas de bord et la discussion est tout à fait utile. Si vous voulez aller à travers toutes les variantes et nuances de l'opérateur, veuillez voir cette fonctionnalité introduction de discussion sur officiel Ruby bug tracker.

10voto

Thomas Deranek Points 85

Méfiez-vous! Si la sécurité de la navigation de l'opérateur est pratique il peut être aussi facile de tromper vous-même en changeant votre logique avec elle. Je recommande d'éviter l'utilisation de l'informatique dans le contrôle de flux. Exemple:

str = nil

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

Dans le premier exemple, str.nil? renvoie la valeur true et str.empty? n'est jamais appelée, provoquant l' puts instruction à exécuter. Dans le deuxième exemple toutefois, str&.empty? retourne nil qui est falsey et l' puts déclaration n'est jamais exécutée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X