Issue #16818 has been updated by inopinatus (Joshua GOODALL).


I visualise a bag of grain. If I'm asked to divide it by three, I will make three piles of grain. If I'm asked to modulate it by three, I will make many piles, each of three grains.

> why you need to refer to complex numbers

This is to illustrate by contradiction that intervals are not sequences, arrays, or matrices in the general case, but measurable subsets of a number set.

> The modulo operator divides a sequence into parts as well

I don't agree that it divides a sequence (since ranges are not sequences), but that's not a crucial difference. For me the key is this:

Both take a interval defined as a subset on a set, and make subsets of it in turn.

In modulus, we specify the measure required of each resulting subset,  
In division, we specify the number of subsets required.

You mentioned equivalence classes, and I agree they are relevant, but as a result my expectation is that the equivalence required of the modulo operator is that of the modular arithmetic it comes from i.e. the congruence relation, thus the modulus operator generates the numbers in the range that satisfy the congruence relation for given n (which is how things are now).

It might follow that I'd expect the division operator to produce an enumerator yielding N equal-length range objects spanning the range, e.g.

    Array (5...14)/3
    #=> [5...8, 8...11, 11...14]

however the implementation of this for all combinations may be more effort than it is worth.


----------------------------------------
Feature #16818: Rename `Range#%` to `Range#/`
https://bugs.ruby-lang.org/issues/16818#change-85304

* Author: sawa (Tsuyoshi Sawada)
* Status: Open
* Priority: Normal
----------------------------------------
`Range#%` was introduced as an alias of `Range#step` by 14697, but it is counter-intuitive and confusing.

Iteration in the following:

```ruby
((5..14) % 3).each{|i| p i}
#>> 5
#>> 8
#>> 11
#>> 14
```

is not based on `x % y` in any sense. In fact, actually applying `% 3` to the selected elements returns a unique value `2`, and it is not obvious how this is related to the iteration.

```ruby
[5, 8, 11, 14].map{|i| i % 3}
# => [2, 2, 2, 2]
```

Rather, the concept seems to be based on `/`. Applying `/ 3` to the relevant elements returns a sequence `1, 2, 3, 4`.

```ruby
[5, 8, 11, 14].map{|i| i / 3}
# => [1, 2, 3, 4]
```

Hence, `(5..14).step(3)` can be interpreted like this: Iterate over the [equivalence class](https://en.wikipedia.org/wiki/Equivalence_class) (quotient set) of range `5..14` yielded by `/ 3`.

Notice that the number of elements in `[5, 8, 11, 14]` is 4, which is `(14 - 5 + 1) / 3.0).ceil`, but is not related to `%`.

So I propose that the alias of `Range#step` should be `Range#/`, and `Range#%` should be deprecated as soon as possible before its use accumulates:

```ruby
((5..14) / 3).each{|i| p i}
#>> 5
#>> 8
#>> 11
#>> 14
```

---

P.S.

And if `Range#%` were to be introduced at all, I would rather expect it to behave like the following:

```ruby
((5..14) % 3).each{|i| p i}
#>> 5
#>> 6
#>> 7
```

which is why I claimed above that the current `Range#%` is confusing.



-- 
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>