一元运算符的行为

时间:2014-02-28 03:28:46

标签: ruby operators operator-overloading

+类的Ruby中重新定义一元Fixnum运算符时,会产生一些奇怪的结果。不完全确定事情发生的原因(特别是行009)。

irb:003> class Fixnum
irb:004>   def +@ #define unary +
irb:005>     15
irb:006>   end
irb:007> end
=> nil
irb:008> 2
=> 2
irb:009> +2
=> 2
irb:010> +(2)
=> 15
irb:011> ++2
=> 15

2 个答案:

答案 0 :(得分:5)

我怀疑你看到解析器行为在解释数字文字方面的副作用。

如果我们创建自己的类:

class C
  def +@
    11
  end
end

然后看一些事情:

> c = C.new
> +c
 => 11 
> ++c
 => 11 

这正是我们期望发生的事情。如果我们使用您的Fixnum一元+覆盖和Fixnum变量:

> n = 23
> +n
 => 15 
> ++n
 => 15 
然后,我们再次看到你所期待的。在这两种情况下,我们都会看到在非文字上调用+@方法的结果。

但是,当我们与您的运营商一起查看+6时:

> +6
 => 6 

未调用+@方法。同样,如果我们覆盖-@

class Fixnum
  def -@
    'pancakes'
  end
end

看看它的作用:

> -42
 => 42

那么这里发生了什么?好吧,Ruby看到+6-42不是6.send(:+@)42.send(:-@)方法调用,而是作为正六和负四十二的单个文字。

如果你开始添加括号+(6)-(42),那么Ruby会看到非文字表达式并最终调用一元方法。同样,当您将一元运算符加倍时。

答案 1 :(得分:2)

这个答案为mu的答案增加了额外的细节。

刚刚了解了ruby的Ripper课程,它清楚地展示了发生的事情:

require 'ripper'

p Ripper.sexp('2')     # => [:program, [[:@int, "2", [1, 0]]]]
p Ripper.sexp('+2')    # => [:program, [[:@int, "+2", [1, 0]]]]
p Ripper.sexp('+(2)')  # => [:program, [[:unary, :+@, [:paren, [[:@int, "2", [1, 2]]]]]]]
p Ripper.sexp('++2')   # => [:program, [[:unary, :+@, [:@int, "+2", [1, 1]]]]]