【问题标题】:How does Ruby's .() operator work?Ruby 的 .() 运算符是如何工作的?
【发布时间】:2013-10-07 03:53:33
【问题描述】:

我最近遇到some code 使用由格式object.(arg1, arg2) 组成的方法调用,但没有很好地解释它的工作原理。请参阅此示例代码:

class TestServiceObject
  def call
    'method'
  end
end

TestServiceObject.new.()
# => 'method'

这种速记的术语是什么?

【问题讨论】:

  • This answer 看起来像您要找的东西。供将来参考,SymbolHound 非常方便查找语言语法...
  • 太棒了!感谢您的提示。

标签: ruby methods syntax service-object


【解决方案1】:

点括号表示法是将参数传递给 Ruby 对象的隐式 call 方法的一种简写方式:

foo = lambda {|bar| puts bar}

foo.call('baz')
#=> baz
foo.('baz')

foo.call('baz') === foo.('baz')
#=> true

另请注意,以下符号也是call 方法的有效(和等效)调用:

foo['baz']
#=> baz
foo::('baz')
#=> baz

在您的示例中,您显式覆盖TestServiceObject 类上的call 方法,以便在调用时返回字符串'method'。因此,您可以显式覆盖call 方法以接受参数:

class TestServiceObject
  def call(foo=nil)
    foo || 'method'
  end
end

TestServiceObject.new.()
#=> method
TestServicesObject.new.('bar')
#=> bar

更新

正如评论者 @LoganSerman 正式指出的那样,速记运算符似乎适用于任何响应 call 的内容,以下示例部分验证了这一点:

m = 12.method("+")

m.call(3)
#=> 15
m.(3)
#=> 15

更新 2

正如评论者@Stefan 也从the documentation on Proc#call 指出:

prc.() 使用给定的参数调用 prc.call()。这是隐藏“调用”的语法糖。

【讨论】:

  • 来自Proc#call: "注意 prc.() 使用给定的参数调用 prc.call() 。这是隐藏“调用”的语法糖。”
  • 为了完整起见,您还可以使用方括号m[3] 和范围解析运算符m::(3) 调用call
  • “点括号表示法是将参数传递给 Ruby 对象上的隐式 call 方法的一种简写方式”——这是错误的。没有“隐式call 方法”之类的东西。 Ruby 没有 隐式方法。您可能会想到 Scala,它是(据我所知)唯一具有隐式含义的语言。
  • "另请注意,以下符号也是 call 方法的有效(和等效)调用:foo['baz']" – 这是错误的:索引运算符转换为对 @987654346 的调用@ 方法,而不是 call 方法。 foo['baz'] 等价于foo.[]('baz'),而不是foo.call('baz')
  • a_proc[arg] 被转换为a_proc.[](arg)not 被转换为a_proc.call(arg)[] 索引运算符的转换不会因对象而神奇地改变,它总是 转换为对[] 方法的调用,而从不call 方法,无论对象是ArrayHashProc 还是FooBarFrobnicatorThingamajingy
【解决方案2】:

obj.(args) 只是通过解析器提供的功能。从技术上讲,它不是别名,但它与在定义 call 方法的对象上调用 obj.call(args) 具有相同的效果。

【讨论】:

    【解决方案3】:
    foo.(bar, baz)
    

    被解释为

    foo.call(bar, baz)
    

    就像

    foo + bar
    

    被解释为

    foo.+(bar)
    

    foo[bar, baz] = quux
    

    被解释为

    foo.[]=(bar, baz, quux)
    

    目的是使调用类函数的对象看起来类似于调用方法:

    foo.(bar, baz) # function
    foo(bar, baz)  # method
    

    尽管在这个问题的其他答案中声称,它与“隐式 call 方法”(Ruby 甚至没有 隐式方法,只有 Scala 有)或索引无关运算符。

    索引运算符被转换为不同的方法调用([]),转换为对call的调用:

    o = Object.new
    
    def o.call(*args); "`call` called with #{args.join(', ')}" end
    
    o.(42)
    # => "`call` called with 42"
    
    o[42]
    # NoMethodError: undefined method `[]' for #<Object:0xdeadbeefc0ffee>
    
    def o.[](*args);   "`[]` called with #{args.join(', ')}"   end
    
    o[42]
    # => "`[]` called with 42"
    

    【讨论】:

    • 红宝石......真是一团糟:)
    猜你喜欢
    • 1970-01-01
    • 2021-11-26
    • 2016-10-25
    • 1970-01-01
    • 1970-01-01
    • 2011-01-05
    • 2018-08-31
    • 2013-08-16
    • 2010-10-02
    相关资源
    最近更新 更多