我在一个 pry 动的 REPL 中闲逛,发现了一些非常有趣的行为:波浪号方法。
Ruby 语法似乎有一个内置的文字一元运算符,~
,只是闲置。
这意味着 ~Object.new
将消息 ~
发送到 Object
的实例:
class Object
def ~
puts 'what are you doing, ruby?'
end
end
~Object.new #=> what are you doing, ruby?
这看起来很酷,但也很神秘。 Matz 本质上是在尝试为我们提供可自定义的一元运算符吗?
我能在 rubydocs 中找到的唯一引用是 operator precedence请注意,它与 !
和 unary +
并列为排名第一的最高优先级运算符,这对一元运算符很有意义。 (有关接下来两个优先级别的有趣勘误表,**
然后是 unary -
,请查看 this question。)除此之外,没有提及此实用程序。
在 ~=、
!~ 和
~>` 问题中,我可以通过搜索找到对这个运算符的两个值得注意的引用,是 this和 this .他们都注意到了它的有用性、怪异性和默默无闻,但没有深入了解它的历史。
在我打算注销 ~
作为为您的对象提供自定义一元运算符行为的一种很酷的方式之后,我发现了它在 ruby 中实际使用的地方 -- fixnum(整数)。
~2
返回 -3
。 ~-1
返回 1
。所以它否定一个整数并减去一个...出于某种原因?
谁能告诉我波浪号运算符在 ruby 中独特和意外行为的目的?
最佳答案
使用pry检查方法:
show-method 1.~
From: numeric.c (C Method):
Owner: Fixnum
Visibility: public
Number of lines: 5
static VALUE
fix_rev(VALUE num)
{
return ~num | FIXNUM_FLAG;
}
虽然这对我来说是难以理解的,但它促使我寻找 C 一元 ~
运算符。一个存在:它是按位 NOT 运算符,它翻转二进制整数的位 (~1010
=> 0101
)。出于某种原因,这转化为比 Ruby 中十进制整数的负数小一。
更重要的是,由于 ruby 是一种面向对象的语言,因此对 ~0b1010
的行为进行编码的正确方法是定义一个方法(我们称它为 ~
)对二进制整数对象执行按位求反。为了实现这一点,ruby 解析器(这里全是猜想)必须将任何对象的 ~obj
解释为 obj.~
,所以你得到所有对象的一元运算符.
这只是一个预感,哪位有更权威或者更明确的答案,请赐教!
--编辑--
正如@7stud 指出的那样,Regexp
类 makes use of it as well ,本质上是将正则表达式与 $_
进行匹配,这是 gets
在当前范围内接收到的最后一个字符串。
正如@Daiku 指出的那样,Fixnum
的按位求反是 also documented .
我认为我的解析器解释解决了一个更大的问题,即为什么 ruby 允许 ~
作为调用 Object#~
的全局一元运算符。
关于Ruby 一元代字号 (`~` ) 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17893483/