Ruby一元平铺(`~`)方法

Ruby一元平铺(`~`)方法,ruby,syntax,operators,literals,Ruby,Syntax,Operators,Literals,我在一个pry REPL中闲逛,发现了一些非常有趣的行为:tilde方法 Ruby语法似乎有一个内置的文本一元运算符,~,就在旁边 这意味着~Object。new将消息~发送到Object的实例: class Object def ~ puts 'what are you doing, ruby?' end end ~Object.new #=> what are you doing, ruby? 这看起来很酷,但很神秘。Matz本质上是想给我们自己的一元运算符吗 在ru

我在一个pry REPL中闲逛,发现了一些非常有趣的行为:tilde方法

Ruby语法似乎有一个内置的文本一元运算符,
~
,就在旁边

这意味着
~Object。new
将消息
~
发送到
Object
的实例:

class Object
  def ~
    puts 'what are you doing, ruby?'
  end
end
~Object.new #=> what are you doing, ruby?
这看起来很酷,但很神秘。Matz本质上是想给我们自己的一元运算符吗

在rubydocs中我能找到的唯一参考是notes,在notes中,它与
一起被列为第一位的最高优先级运算符
一元运算符+
这对一元运算符很有意义。(有关下两个优先级级别的有趣勘误表,
***
然后是
一元-
,请查看。)除此之外,没有提及此实用程序

我可以在
~=,
中通过搜索找到对该运算符的两个值得注意的引用~<代码>,和~>`问题是和。他们都注意到了它的有用性、古怪性和默默无闻性,而没有深入了解它的历史

在我打算把
~
作为为对象提供自定义一元运算符行为的一种很酷的方法,写下来之后,我找到了一个在ruby中实际使用它的地方--fixnum(整数)

~2
返回
-3
~-1
返回
1
。所以它对一个整数求反,然后减去一。。。出于某种原因


有人能告诉我tilde操作符在ruby中的独特和意外行为的目的吗?

pickaxe 1.8中有几个地方提到过它,例如String类。然而,在ruby 1.8.7中,它不能在所宣传的String类上工作。它适用于Regexp类:

print "Enter something: "
input = gets
pattern = 'hello'
puts ~ /#{pattern}/

--output:--
Enter something: 01hello
2

它对String类的作用应该类似。

对于
fixnum
,它是一的补码,在二进制中,它将所有的1和0翻转到相反的值。这是文件:。要理解为什么它会给出示例中的值,您需要了解负数是如何用二进制表示的。我不知道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
类本质上是将regex与
$\uu
相匹配,
接收到的最后一个字符串在当前范围内

正如@Daiku所指出的,
Fixnum
s的位求反是


我认为我的解析器解释解决了一个更大的问题,即为什么ruby允许
~
作为调用
对象的全局一元运算符#
在ruby中,
~
是二进制的补码运算符。一个人的补码只是翻转一个数字的位,结果这个数字现在在算术上是负数

例如,32位二进制(Fixnum的大小)中的2是0000 0000 0010,因此~2等于1的补码中的1111111111111101

然而,正如您已经注意到并进一步详细讨论的那样,Ruby版本的one补码的实现方式似乎有所不同,因为它不仅使整数为负数,而且还从中减去1。我不知道为什么会这样,但似乎确实如此。

  • ~(Bignum)
  • ~(络合物)
  • ~(Fixnum)
  • ~(Regexp)
  • ~(IPAddr)
  • ~(整数)
  • ~(Regexp)
每一项都记录在文档中

此列表来自Ruby 2.6的文档


这个方法的行为“大体上”是您想要的,正如您在对象类上定义的名为
~
的方法所描述的那样。由实现维护人员定义的核心类上的行为似乎有很好的文档记录,因此这些对象不应该有意外的行为。

我认为文档记录必须是固定的,因为
~
操作符不是一个补足,而是两个补足。看,这正是我自己开始胡闹时的想法!然而,二的补码不是颠倒位加一,不是减一吗??“我认为文档必须修复…”什么文档?这里一切看起来都很好。答案中链接的那篇文章是垃圾。“因此,Ruby中的~运算符表示{-x-1}而不是{~x}。”这是完全错误的<代码>~x
在ruby中与任何语言都是一样的:按位补码。Ruby使用2的补码(和其他任何人一样),因此它可以比1的补码多表示一个数,这意味着一个数的按位补码的大小与原始数不同。这里一切都很好。关于~bitwise运算符的另一个答案似乎可以更好地解释:正如我们在这里讨论的,bitwise complete是一个一的补码,但是当涉及负数时,有一个有趣的交互作用,因为负数是如何存储的:不确定为什么要进行向下投票