Issue #16990 has been updated by Student (Nathan Zook).


mame (Yusuke Endoh) wrote in #note-9:
> I expect that `ary + set` return a Set, not an Array, unless it raises an exception.
> 
> > Otherwise array += set would turn the variable array to a Set and that would be a surprise.
> 
> It is a surprise if `ary + set` returns a collection object that is ordered and that has multiple instances in its elements.
> To me. `ary += set` looks like `int_val += float`. It is not a surprise to me that it changes the type of `int_val`.

I found implicit conversions of values in K&R to be an abomination BEFORE I became aware of the many, many bugs & security issues that came from them.

In the world of objects, a + b = c is expected either to have the same class as a, or of the nearest common ancestor of the classes of a & b.  Of course, in the Ruby type system, this is Object.  Philosophically, it is pretty clear that Array is a descendant class of Set.  Arrays add ordering, and thereby multiplicity and otherwise behave as Sets.  HOWEVER--at some point it is important, even critical, to bow to the culture.  The culture of programming (outside of LISP?) is that Arrays are the thing that "everyone" works with "all the time", while Sets are reserved for specialists or special situations.  As a mathematician, I am loathe to use Arrays when I mean Sets, but then again, I never use ':' as a string quote character, either...

I find the exception that "everyone" does with int_val += float "unsurprising" because "everyone" has been taught it since K&R.   It is horrible practice, and needs to be avoided.  For the case of [1,2] += {1,2}, it is far from clear to me that the operation is sufficiently well-defined in the industry to be able to choose a solution.  No matter what is chosen, the results are going to surprise a lot of folks.  Throwing an exception says "we're not going to assume we can read your mind on this one."

My solution would be to define Array.add([1,2], {1,2}) and Set.add([1,2], {1,2}).  Internally, the obnoxious conversions back & forth can be avoided.  Externally, its really clear what will come back.


----------------------------------------
Feature #16990: Sets: operators compatibility with Array
https://bugs.ruby-lang.org/issues/16990#change-90554

* Author: marcandre (Marc-Andre Lafortune)
* Status: Open
* Priority: Normal
----------------------------------------
We currently have `set <operator> array` work fine:

```ruby
Set[1] + [2] # => Set[1, 2]
```

Nothing works in the reverse order:

```ruby
[1] + Set[2] # => no implicit conversion of Set into Array
# should be:
[1] + Set[2] # => [1, 2]
```

#### set-like operators

Note that the situation is particularly frustrating for `&`, `|` and `-`.
If someone wants to do `ary - set`, one **has** to do `ary - set.to_a` which will, internally, do a `to_set`, so what is happening is `set.to_a.to_set`!! (assuming `ary` is over `SMALL_ARRAY_LEN == 16` size, otherwise it's still doing in `O(ary * set)` instead of `O(ary)`).

The same holds with `&` and `|`; see order issue as to why this can *not* (officially) be done any other way.

Reminder:
```ruby
ary & ary.reverse # => ary
Set[*ary] & Set[*ary.reverse]  # => Set[*ary.reverse], officially order is indeterminate
```




-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>