【问题标题】:What does &. (ampersand dot) mean in Ruby?& 是什么意思。 (& 点)在 Ruby 中是什么意思?
【发布时间】:2016-08-17 04:41:48
【问题描述】:

我遇到了这行 ruby​​ 代码。这里面&.是什么意思?

@object&.method

【问题讨论】:

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


    【解决方案1】:

    它被称为安全导航运算符。在 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

    您可以使用&. 指定接收者,然后my_method 不会被调用 当接收者为nil 时,结果为nil。在这种情况下, 不评估 my_method 的参数。

    【讨论】:

    • 实际上,它的工作方式类似于try! 方法,而不是try
    【解决方案2】:

    注意:尽管@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

    【讨论】:

    • 什么是'.?' ?我认为已经决定不能使用这种语法。我只能得到“&”。工作。
    • 没错,正如我写的.? 和其他选项被考虑,但&. 被选中!所以,只有&. 可以工作。
    • 哦,对不起,我没有仔细阅读直到最后。如果这些例子有正确的语法不是更好吗?
    • @KeithBennett 我明白你的意思。在我的第一个示例中,我有一个错字。你是对的,它必须是&. 而不是.?,我的错。更新了我的答案。感谢您的提醒!
    • @Uzbekjon Edge case 示例(选项 1)中仍有错字:user.?profile 应为 user&.profile(无法自己编辑,因为它只是一个1 个字符编辑!)。
    【解决方案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 语句。

    【讨论】:

    • 有趣,虽然从技术上讲,在您的第一条语句中 str.nil? 是正确的(如您所说),这意味着实际上根本不会调用 str.empty?(这就是 || 运算符的工作方式)。你的陈述的其余部分是正确的。
    • 哦,很好。我不知道我是怎么错过的。我会更正我的帖子。谢谢!
    • 确实,使用错误的逻辑要容易得多,但是您在这里检查的是不同的东西。第二行相当于 if str && str.empty?不为零||空的。安全导航操作符仍然完全有效地用于流控制puts "hello" unless str&.present?(rails 仅适用于当前?方法)
    【解决方案4】:

    它用于nil检查,例如在kotlin和swift中 例如; 使用 Object -> Swift 和 Kotlin

    model = car?.model
    

    如果我们没有在 car 类中定义模型值,这个模型可以是 nil(Swift) 或 null(Kotlin)。 我们在 ruby​​ 中使用 & 号而不是问号

    model = car&.model
    

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

    【讨论】:

      猜你喜欢
      • 2011-04-18
      • 2011-08-12
      • 2017-06-11
      • 2018-03-05
      • 2023-03-27
      • 1970-01-01
      • 2011-10-14
      • 2014-06-21
      • 2010-12-28
      相关资源
      最近更新 更多