What means &. (ampersand) in Ruby?

I came across this line of ruby ​​code. What does &. mean &. in that?

 @object&.method 
+135
operators syntax parameter-passing ruby
Apr 23 '16 at 15:22
source share
4 answers

This is called the safe navigation operator. Introduced in Ruby 2.3.0, it allows you to call methods on objects without worrying about the object being nil ( undefined method for nil:NilClass errors undefined method for nil:NilClass ), similar to the try method in Rails .

So you can write

 @person&.spouse&.name 

instead

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

From the docs :

my_object.my_method

This sends the message my_method my_object. Any object can be a recipient, but depending on the visibility of the method, sending a message may cause a NoMethodError error.

You can use &. to indicate the receiver, then my_method is not called, and the result is zero when the receiver is zero. In this case, the arguments to my_method are not evaluated.

+172
Apr 23 '16 at 15:23
source share

Note. Although @Santosh gave a clear and complete answer, I would like to add some more background and add an important note regarding its use with non-instance variables.




It is called “ Safe Navigator” (“Optional Chain Operator”, “Operator with Zero Condition”, etc.). Matz seems to call this a “lone operator.” This was introduced in Ruby 2.3 . It sends a method to an object only if it is not nil .

Example:

 # Call method `.profile` on `user` only if `user` is not `nil` @user&.profile # Equivalent to unless @user.nil? @user.profile end 

"Edge case" with local variables:

Please note that the above code uses instance variables. If you want to use a safe navigation operator with local variables, you will need to first verify that the local variables are defined.

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

To fix this problem, check if your local variable is defined, or set it to nil:

 # 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 

Method Background

Rails has a try method that basically does the same thing. It uses the send method to call the method. Matz suggested that it is slow, and this should be a built-in language feature.

Many other programming languages ​​have a similar feature: Objective-C, Swift, Python, Scala, CoffeeScript, etc. However, the general syntax is ?. (question dot). But this syntax was not accepted by Ruby. Since ? allowed in method names and therefore character sequence ?. is already valid Ruby code. For example:

 2.even?.class # => TrueClass 

That's why the Ruby community had to come up with a different syntax. It was an active discussion, and various options were considered ( .? , ? , && , etc.). Here is a list of some considerations:

 u.?profile.?thumbnails u\profile\thumbnails u!profile!thumbnails u ? .profile ? .thumbnails u && .profile && .thumbnails # And finally u&.profile&.thumbnails 

When choosing syntax, the developers looked at different boundary cases, and the discussion is quite useful for going through. If you want to see all the options and nuances of the operator, see the discussion of this function on the official tracker buffer for Ruby.

+53
Apr 23 '16 at 16:32
source share

Be careful! Although the safe navigation operator is convenient, it can also easily fool itself and change its logic. I recommend avoiding using this in flow control. Example:

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

In the first example, str.nil? returns true , and str.empty? never called, as a result of which the puts statement is executed. In the second example, however, str&.empty? returns nil , which is incorrect, and the puts statement is never executed.

+7
Feb 07 '18 at 15:13
source share

it is used to check for zero, for example, in kotlin and swift; with object → Swift and Kotlin

 model = car?.model 

this model can be nil (Swift) or null (Kotlin) if we have not defined the value of the model in the car class. we use this ampersand instead of a question mark in ruby

 model = car&.model 

if you use car.model without an ampersand and if the model is zero, the system will not be able to continue working.

+1
Jan 21 '19 at 3:26
source share



All Articles