【问题标题】:Unary operators behavior一元运算符行为
【发布时间】:2014-03-31 21:23:24
【问题描述】:

Fixnum 类的 Ruby 中重新定义一元 + 运算符时出现了一些奇怪的结果。不完全确定为什么事情会以现在的方式发生(特别是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)中,2是方法+的参数;与+ 2 相同。没有方法++,所以++2被解释为+(+2),或者+(2)
  • 那么你得到的是+ 2 调用了+@ 方法,而+2 只是被解析器/解释器视为文字2

标签: ruby operators operator-overloading


【解决方案1】:

此答案为 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]]]]]

【讨论】:

  • 我刚刚看到你在here 上玩这些东西。
  • 哈哈是的,这就是让我想到这个问题的原因。 Ripper 似乎是回答此类问题的好工具
【解决方案2】:

我怀疑您看到了解析器在解释数字文字时的行为的副作用。

如果我们创建自己的类:

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 会看到非文字表达式并最终调用一元方法。同样,当您将一元运算符加倍时。

【讨论】:

  • 添加了一个您可能有兴趣看到的我自己的答案 - 它只是表明您所说的是正确的,但无论如何都很好看
猜你喜欢
  • 1970-01-01
  • 2018-09-18
  • 1970-01-01
  • 2015-03-30
  • 1970-01-01
  • 1970-01-01
  • 2012-08-08
  • 2019-05-18
  • 2017-03-05
相关资源
最近更新 更多