Feature #13606
closedEnumerator equality and comparison
Description
In Ruby, most objects are compared by value. What do you think about Enumerator
s following the same pattern? I think this would greatly increase the expressiveness of Ruby.
Proposal:
Two Enumerator
s should be considered equal (==
) if they yield the same number of elements and these elements are equal (==
).
If both of the Enumerator
s are infinite, the equality operator never terminates.
<=>
should be handled similarly.
Updated by duerst (Martin Dürst) over 7 years ago
- Status changed from Open to Feedback
Sounds interesting in theory, but do you have actual use cases? And do you think that the potential inefficiency is worth it?
Updated by shevegen (Robert A. Heiler) over 7 years ago
I am not even sure that I understand the proposal.
If I understood it correctly then two enumerable objects (did I get this part right)
should return true if they behave/return the same? I think I can see it being
related to duck typing... but they are not entirely the same are they? Different
object id for most objects for example. But it also may be that I did not fully
understand the proposal yet.
What would the speed penalty be if one exists? I guess the latter one could be
handled by some "behavioural switch" for people who need the behaviour
desscribed in the proposal, so a use-case example would be helpful.
Updated by glebm (Gleb Mazovetskiy) over 7 years ago
shevegen (Robert A. Heiler) wrote:
[...] but they are not entirely the same are they? Different
object id for most objects for example. But it also may be that I did not fully
understand the proposal yet.
Most objects in Ruby are compared semantically if the object IDs are different, including Array
and Hash
.
What would the speed penalty be if one exists?
If the Enumerator
s have different object_id
s, previous the equality check was O(1)
but is O(n)
with this proposal (just like for Array
).
I guess the latter one could be
handled by some "behavioural switch" for people who need the behaviour
desscribed in the proposal, so a use-case example would be helpful.
I am not proposing a behavioural switch. This should be a backwards-incompatible change.
Use cases are the same as for arrays, except when the "arrays" are "lazy".
Example:
[1, 2, 3].reverse == [3, 2, 1]
#=> true
[1, 2, 3].reverse_each == [3, 2, 1]
#=> false
[1, 2, 3].reverse_each == [1, 2, 3].reverse_each
#=> false
With this proposal, the last two are also true
.
Updated by glebm (Gleb Mazovetskiy) over 7 years ago
duerst (Martin Dürst) wrote:
Sounds interesting in theory, but do you have actual use cases? And do you think that the potential inefficiency is worth it?
The use cases are the same as for comparing Array
s.
The potential inefficiency is not a problem because if you need to compare Enumerator
s by object_id
you can do it using equal?
. If the object_id
s are the same, both the current and the proposed comparisons take constant time.
Updated by MSP-Greg (Greg L) over 7 years ago
Could be helpful, but some Enumerators
are not ordered. So how would ==
work for 'hash like' objects (assuming they're not based on a hash, which has an ==
operator)?
I suppose it could be considered 'restricted' to ordered collections...
Updated by glebm (Gleb Mazovetskiy) over 7 years ago
MSP-Greg (Greg L) wrote:
Could be helpful, but some
Enumerators
are not ordered. So how would==
work for 'hash like' objects (assuming they're not based on a hash, which has an==
operator)?I suppose it could be considered 'restricted' to ordered collections...
Equal objects should produce equal results when used.
From this perspective on equality, enumerators that yield in different order should not be considered equal, even if they internally yield elements from an unordered collection.
If the enumerator yields in a different order every time it's called, then the comparison is not guaranteed to return the same result every time. This is a rare edge case though.
Updated by duerst (Martin Dürst) over 7 years ago
MSP-Greg (Greg L) wrote:
Could be helpful, but some
Enumerators
are not ordered.
All Enumerators
are ordered. The order is defined by the each
method, or alternatively by the to_a
method.
Actually, I wonder if there's any difference between what the OP wants and
enumerator_A.to_a == enumerator_B.to_a
Although direct comparison for equality would be shorter, the above makes it explicit that efficiency may be low.
Updated by glebm (Gleb Mazovetskiy) over 7 years ago
duerst (Martin Dürst) wrote:
Actually, I wonder if there's any difference between what the OP wants and
enumerator_A.to_a == enumerator_B.to_a
The above allocates Arrays, Enumerator equality would not.
Updated by knu (Akinori MUSHA) about 7 years ago
- Status changed from Feedback to Rejected
Without any actual use case, there would be no effective definition of equality for enumerators.
FWIW, the initial design policy is, Enumerator is an abstract entity that only guarantees it responds to each
for enumeration, and it's not your problem as to what's behind a given enumerator. You shouldn't have to care about the equality in the first place.