2017-03-10 69 views
1

我想知道Ruby中的点和操作符表示法之间的区别。这里有一些例子点和操作符表示法之间的区别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!" 

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

+0

对于一些方法,你不会找到一个运营商的符号或点符号。例如'5.add(3)',除非你实现它。另一个例子是使用运算符调用.length方法 - 你不能这样做。谈到效率时,我们实际上应该有一些可以比较的东西。如果你提供了一个两种方法的例子,我们可以做到这一点。 –

+0

首先想到的是:基准测试(ruby甚至有内建的基准测试模块) – Jokester

+0

“既然都调用方法并返回类似的对象,我怀疑点符号或运算符方法是更有效的。” - 我不遵循你的逻辑:你基本上在说“因为两者完全相同,所以必须更有效率”。但这没有意义:如果他们都做同样的事情,你会期望他们是完全一样的效率。 –

回答

4

[...]如果我们调用使用点.符号上对象的方法,然后在那里是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 P ro(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) 

结果不确定。

在使用内联运算符而不是点方法等价物时,性能几乎没有可测量的差异。

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

参考文献:

+1

谢谢@sonna。你的解释非常好。 – aprogrammer

0

TL;博士:操作符号是点标记语法糖。我不希望有任何明显的性能差异。

如果你看一下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)); 
}