水晶兰中的"&-="运算符是什么?

问题描述 投票:0回答:1

我刚刚知道有 &-= Crystal中的操作员。它是做什么的呢?

下面是一个例子 Mutex#try_lock:

private def try_lock
  i = 1000
  while @state.swap(1) != 0
    while @state.get != 0
      Intrinsics.pause
      i &-= 1
      return false if i == 0
    end
  end

  true
end

试了一下,我看不出和熟悉的有什么区别。-= 操作符。例如,这两个片段产生了相同的输出。

i = 1000
while i != 0
  puts i
  i -= 1
end
i = 1000
while i != 0
  puts i
  i &-= 1
end
crystal-lang
1个回答
6
投票

谜题的第一块是要认识到 a &-= b 只是语法上的糖分 a = a &- b. 或者更一般地说 a op= b 是语法糖 a = a op b. 语文参考资料在 "联合转让 "中对此作了详细说明。操作人员.

现在我们要问的是 &- 又与 -? 遗憾的是,在写这篇文章的时候,API文档对此还很平静。语言参考也不是很详细,但是在上面的操作符页面我们可以找到。

- 减法 &- 包干减法

那么什么是包装减法呢?嗯,Crystal有固定大小的数字类型。所以它们可能会溢出,或者在这种情况下可能会不足。这是什么意思呢?我们举个例子。

# We have something to sell! Let's keep track of how many!
# It doesn't really make sense to have negative something left,
# so an unsigned integer ought to this.
items_left = 2u32

# Just made the first sell! Let's remember
items_left -= 1

# People seem to actually like this
items_left -= 1

# I could do this all day!
items_left -= 1 # => Unhandled exception: Arithmetic overflow (OverflowError)

# Oh no what happend?

所以程序试图从下面 0,其中 UInt32 类型不能代表。它下溢了。如果Crystal不做这个检查,CPU就会很高兴地在整数类型上绕来绕去,我们就可以得到 4294967295items_left (UInt32::MAX).

但有时,在低级代码中,这种行为是我们想要的。比如说如果我们在统计一些统计数据,比如说发送的数据包,如果这个计数器溢出或不足,在这种情况下,我们不希望程序失败,绕过就可以了。或者我们有一些对性能敏感的代码,确信它的行为是正确的,永远不会溢出,所以我们不想在检查操作是否刚刚溢出上付出额外的CPU周期。

对于这些情况,我们可以使用 & 前缀的数学运算符。它们只是简单地执行操作,而没有任何溢出检查。如果我们使用 &- 而不是 - 在上面的例子中,我们会有 4294967295items_left 现在。

在一般情况下,你知道万一你需要或有好处的包装运营商。如果有疑问,就当它们不存在。

© www.soinside.com 2019 - 2024. All rights reserved.