【问题标题】:Difference between dot and operator notation Ruby点和运算符符号Ruby之间的区别
【发布时间】:2017-03-10 01:07:04
【问题描述】:

我想知道 Ruby 中点和运算符符号之间的区别。这里有一些例子

# Use dot notation to invoke a method 
"I'm thirty one characters long!".length
# => 31

# Use operator notation to invoke a method
"Kit" + "tens!"
# => "Kittens!"

由于调用一个方法并返回相似的对象,我怀疑点表示法或运算符方法更有效。任何想法表示赞赏。

【问题讨论】:

  • 对于某些方法,您不会找到运算符符号或点符号。例如5.add(3),除非你实现它。另一个例子是使用操作符调用 .length 方法——你不能那样做。在谈论效率时,我们实际上应该有一些可以比较的东西。如果您提供了一个包含双向调用方法的示例,我们可以做到这一点。
  • 第一个想法:对它们进行基准测试(ruby 甚至有一个内置的基准模块)
  • “由于调用一个方法并返回相似的对象,我怀疑点符号或运算符方法更有效。” – 我不遵循您的逻辑:您基本上是在说“由于两者都做完全相同的事情,因此必须更有效率”。但这没有任何意义:如果它们都做完全相同的事情,那么您会期望它们的效率完全相同。

标签: ruby


【解决方案1】:

[...] 如果我们使用点 . 表示法调用对象上的方法,那么 2 + 3 * 4 中的点在哪里?

诀窍是:Ruby 会默默地为您添加它们。如果你写如下代码:

number = 2 + 3 * 4

然后 Ruby 会将其翻译成以下内容:

number = 2.+(3.*(4))

-- Operators are methods | Ruby for Beginners

至于性能差异:

# bmbm_dot_vs_operators.rb
require "benchmark"

Benchmark.bmbm do |x|
  x.report("dots") { 2.+(3.*(4)) }
  x.report("operators") { 2 + 3 * 4 }

  x.report("operators") { 4 + 2 * 3 }
  x.report("dots") { 4.+(2.*(3)) }
end

在我的系统(MacBook Pro(Retina,15 英寸,2013 年末))上运行时,会产生以下结果

$ ruby bmbm_dot_vs_operators.rb
Rehearsal ---------------------------------------------
dots        0.000000   0.000000   0.000000 (  0.000005)
operators   0.000000   0.000000   0.000000 (  0.000002)
operators   0.000000   0.000000   0.000000 (  0.000002)
dots        0.000000   0.000000   0.000000 (  0.000002)
------------------------------------ total: 0.000000sec

                user     system      total        real
dots        0.000000   0.000000   0.000000 (  0.000002)
operators   0.000000   0.000000   0.000000 (  0.000002)
operators   0.000000   0.000000   0.000000 (  0.000002)
dots        0.000000   0.000000   0.000000 (  0.000002)

结果尚无定论。

使用内联运算符与等效的点方法相比,性能几乎没有差异。

此外,第一个操作总是最慢的,因此为什么要多次包含它以比较基准测试顺序。

参考资料:

【讨论】:

  • 谢谢@sonna。你的解释太棒了。
【解决方案2】:

tl;dr:运算符符号是点符号的语法糖。我预计不会有任何明显的性能差异。

如果您查看Ruby's grammar,您会发现以下内容:

call_bin_op(recv,id,arg1) call_bin_op_gen(parser, (recv),(id),(arg1))

这基本上是说像您的示例中的 + 这样的二元运算符有一个接收器、一个 ID(将其视为 CRuby 的符号)和一个参数,就像带有一个参数的方法调用一样。

如果您再查看call_bin_op_gen,您会发现它实际上转化为调用:

static NODE *
call_bin_op_gen(struct parser_params *parser, NODE *recv, ID id, NODE *arg1)
{
    value_expr(recv);
    value_expr(arg1);
    return NEW_CALL(recv, id, NEW_LIST(arg1));
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-18
    • 1970-01-01
    • 2011-05-24
    • 2016-05-18
    • 2011-10-22
    • 2012-10-06
    • 2015-12-09
    • 2010-12-30
    相关资源
    最近更新 更多