Ruby为什么有”Array#<=>“而没有”Array#<"?

huangapple go评论67阅读模式
英文:

Why does Ruby have the "Array#<=>" but not "Array#<"?

问题

你可以像这样比较两个数组。

我想知道为什么没有像&gt;&lt;等运算符。这是有意设计的吗?如果是的话,这方面的历史是什么?

英文:

You can compare two arrays like this.

p ([1, 2] &lt;=&gt; [1, 3]) &lt; 0 # [1, 2] &lt; [1, 3]
p ([1, 2] &lt;=&gt; [1, 3]) &gt; 0 # [1, 2] &gt; [1, 3]
p ([1, 2] &lt;=&gt; [1, 3]) == 0 # [1, 2] == [1, 3]

I wonder why there are no operators like &gt;, &lt;, etc. Is it an intentional design or not? If it is, what is the history on it?

答案1

得分: 1

我对原帖的意见:

> 当你将数组用作数据结构的键时,比如优先队列(heap),数组比较很有用。

在这种情况下,我更喜欢有明确的逻辑。例如:

class Key
  attr_reader :array

  def initialize(array)
    @array = array
  end

  def <(other)
    (array <=> other.array) < 0
  end

  def >(other)
    (array <=> other.array) > 0
  end

  def ==(other)
    (array <=> other.array) == 0
  end
end

key1 = Key.new([1, 2])
key2 = Key.new([1, 3])

p key1 < key2
p key1 > key2
p key1 == key2

这段代码实现了数组比较的逻辑。

英文:

My five cents to OP comment:

> The array comparison is useful when you use an array as a key of the data structure, such as a priority queue(heap).

In that case I would prefer to have an explicit logic for that. For example:

class Key
  attr_reader :array

  def initialize(array)
    @array = array
  end

  def &lt;(other)
    (array &lt;=&gt; other.array) &lt; 0
  end

  def &gt;(other)
    (array &lt;=&gt; other.array) &gt; 0
  end

  def ==(other)
    (array &lt;=&gt; other.array) == 0
  end
end

key1 = Key.new([1, 2])
key2 = Key.new([1, 3])

p key1 &lt; key2
p key1 &gt; key2
p key1 == key2

答案2

得分: 1

我根据Stefan提供的信息来回答我的问题。

这是Ruby的原始作者Matz故意设计的。按字典顺序比较两个数组是一个自然而有用的想法。但它们并不总是可比较的,就像这个例子。

p [1, 2] <=> [1, 'x'] # 这会返回nil,因为你不能比较2和'x'。

Matz担心提供普通的比较运算符会给人一种错误的印象,即数组总是可以比较的。但他无法完全放弃比较数组,所以提供了特殊的<=>运算符。您可以在相关功能请求的回答中阅读他的回答:Feature#5574 - Make arrays comparable

因此,这个设计决策是一种有主见的决策,而不是技术性的决策。在我个人看来,如果提供普通运算符并在数组不可比较时引发异常会更一致。(我是Ruby和Python的粉丝。)

英文:

I'm answering my own question based on the information provided by Stefan.

It was an intentional design by Matz, the original author of Ruby. Comparing two arrays by comparing elements in lexicographical order is a natural and useful idea. But they are not always comparable, like this example.

p [1, 2] &lt;=&gt; [1, &#39;x&#39;] # This returns nil, because you can&#39;t compare 2 and &#39;x&#39;.

Matz was concerned that providing ordinary comparison operators would give a false impression that arrays are always comparable. But he couldn't give up comparing arrays entirely and provided the special &lt;=&gt; operator. You can read his answer on the related feature request at Feature#5574 - Make arrays comparable.

So the design decision was an opinionated one rather than a technical one. In my humble opinion, it would be more consistent if ordinary operators are provided and an exception is raised when arrays are not comparable. (I'm a fan of both Ruby and Python.)

huangapple
  • 本文由 发表于 2023年7月6日 12:05:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76625421.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定