我在一个狡猾的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。)除此之外,不提及此实用程序。
我可以通过在~=,
!〜, and
〜>`问题中搜索找到对此运算符的两个值得注意的引用是this和this。他们都注意到它的实用性,古怪性和默默无闻,而没有进入其历史。
在我即将注销~
作为为对象提供自定义一元操作符行为的一种很酷的方法之后,我找到了一个实际用于ruby的地方 - fixnum(整数)。
~2
返回-3
。 ~-1
返回1
。所以它否定一个整数并减去一个......出于某种原因?
任何人都可以启发我作为波形符操作符在ruby中的独特和意外行为的目的吗?
答案 0 :(得分:3)
对于fixnum
,它是一个补码,它以二进制形式将所有的1和0翻转为相反的值。这是文档:http://www.ruby-doc.org/core-2.0/Fixnum.html#method-i-7E。要理解为什么它给出了它在示例中所做的值,您需要了解负数如何用二进制表示。为什么ruby提供这个,我不知道。 Two's complement通常是现代计算机中使用的。{{3}}。它的优点是基本数学运算的相同规则适用于正数和负数。
答案 1 :(得分:3)
使用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
s的按位否定是also documented。
我认为我的解析器解释解决了为什么ruby允许~
作为调用Object#~
的全局一元运算符的更大问题。
答案 2 :(得分:1)
~
是Ruby中的二进制补码运算符。唯一的补充只是翻转一个数字的位,这个数字现在是算术上的负数。
例如,32位(Fixnum的大小)二进制中的2是0000 0000 0000 0010,因此~2将等于1111 1111 1111 1101的补码。
然而,正如您已经注意到并this article进一步详细讨论的那样,Ruby的一个补充版本似乎有不同的实现,因为它不仅使整数为负,而且从中减去1。我不知道为什么会这样,但似乎确实如此。
答案 3 :(得分:0)
在镐1.8的几个地方提到过,例如String类。但是,在ruby 1.8.7中,它不像广告中那样对String类起作用。它适用于Regexp类:
print "Enter something: "
input = gets
pattern = 'hello'
puts ~ /#{pattern}/
--output:--
Enter something: 01hello
2
它应该类似于String类。
答案 4 :(得分:0)
每篇文章均记录在文档中。
此列表来自Ruby 2.0的文档
这个方法“at large”的行为基本上是你想要的,正如你在Object类中定义了一个名为~
的方法时所描述的那样。由实现维护者定义的核心类的行为似乎已被很好地记录,因此它不应该对这些对象有意外行为。