什么和&amp ;. (&符号)在Ruby中意味着什么?

时间:2016-04-23 15:22:46

标签: ruby syntax operators parameter-passing ruby-2.3

我遇到了这行ruby代码。 &.在这里意味着什么?

@object&.method

4 个答案:

答案 0 :(得分:159)

它被称为安全导航操作员。在Ruby 2.3.0中引入,它允许您调用对象上的方法,而不必担心对象可能是nil(避免undefined method for nil:NilClass错误),类似于try method in Rails

所以你可以写

@person&.spouse&.name

而不是

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

来自Docs

  

my_object.my_method

     

这会将my_method消息发送到my_object。任何   对象可以是接收者,但取决于方法的可见性   发送消息可能会引发NoMethodError。

     

你可以使用&amp ;.指定一个接收器,然后不调用my_method   当接收器为零时,结果为零。在那种情况下,   不评估my_method的参数。

答案 1 :(得分:48)

注意:尽管@Santosh给出了一个清晰而完整的答案,但我想添加更多背景,并添加一个重要说明,关于它与非实例变量一起使用。

它被称为“Safe Navigation Operator”(又名“可选链接运算符”,“空条件运算符”等等。)。 Matz似乎称之为“孤独的运营商”。那是introduced in Ruby 2.3。仅当对象不是nil时才会向对象发送方法。

实施例

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

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

带有局部变量的“边缘情况”:

请注意,上面的代码使用实例变量。如果要将安全导航操作符与局部变量一起使用,则必须首先检查是否定义了局部变量。

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

要解决此问题,请检查您的局部变量是先定义还是将其设置为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

方法背景

Rails有try方法基本上做同样的事情。它在内部使用send方法来调用方法。 Matz suggested它很慢,这应该是内置语言功能。

许多其他编程语言具有类似的功能:Objective C,Swift,Python,Scala,CoffeeScript等。但是,常见的语法是?.(问题点)。但是,Ruby不能采用这种语法。因为方法名称中允许?,因此?.符号序列已经是有效的Ruby代码。例如:

2.even?.class  # => TrueClass

这就是为什么Ruby社区必须提出不同的语法。这是一次积极的讨论,并考虑了不同的选项(.??&&等。以下列出了一些注意事项:

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

# And finally
u&.profile&.thumbnails

在选择语法时,开发人员会查看不同的边缘情况,讨论非常有用。如果您想了解运营商的所有变体和细微差别,请参阅官方Ruby问题跟踪器上的this feature introduction discussion

答案 2 :(得分:3)

小心!虽然安全导航操作员很方便,但也很容易欺骗自己用它来改变你的逻辑。我建议避免在流量控制中使用它。例如:

str = nil

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

在第一个示例中,str.nil?返回true,永远不会调用str.empty?,导致puts语句被执行。但是,在第二个示例中,str&.empty?返回nil,这是假的,并且永远不会执行puts语句。

答案 3 :(得分:1)

它用于零检查,例如在kotlin和swift中 例如; 与对象-> Swift和Kotlin

model = car?.model

如果我们尚未在car类中定义模型值,则此模型可以为nil(Swift)或null(Kotlin)。 我们使用与号代替红宝石中的问号

model = car&.model

如果使用不带&符号的car.model,并且如果model为nil,则系统无法继续运行。