What does &. (ampersand dot) mean in Ruby?

匿名 (未验证) 提交于 2019-12-03 03:10:03

问题:

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

@object&.method

回答1:

It is called the Safe Navigation Operator. Introduced in Ruby 2.3.0, it lets you call methods on objects without worrying that the object may be nil(Avoiding an undefined method for nil:NilClass error), similar to the try method in Rails.

So you can write

@person&.spouse&.name

instead of

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


回答2:

Note: Even though @Santosh gave a clear and full answer, I would like add some more background and add an important note regarding its use with non instance variables.


It is called "Safe Navigation Operator" (aka "Optional chaining operator", "Null-conditional operator", etc.). Matz seems to call it "lonely operator". It 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, above code uses instance variables. If you want to use safe navigation operator with local variables, you will have to check that your local variables are defined first.

# `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 issue, check if your local variable is defined first 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 try method that basically does the same. It uses send method internally to call a method. Matz suggested that it is slow and this should be a built-in language feature.

Many other programming languages have similar feature: Objective C, Swift, Python, Scala, CoffeeScript, etc. However, a common syntax is ?. (question dot). But, this syntax could not be adopted by Ruby. Because ? was allowed in method names and thus, ?. symbol sequence is already a valid Ruby code. For example:

2.even?.class  # => TrueClass

That's why Ruby community had to come up with different syntax. It was an active discussion and different 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

While choosing the syntax, developers looked at different edge cases and the discussion is quite useful to go through. If you want to go through all variants and nuance of the operator, please see this feature introduction discussion on official Ruby issue tracker.



回答3:

Be wary! Though the safe navigation operator is convenient it can also be easy to trick yourself into changing your logic with it. I recommend avoiding the use of it 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 then str.empty? returns true, causing the puts statement to be executed. In the second example however, str&.empty? returns nil which is falsey, and the puts statement is never executed



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!