Forum: Ruby-core [ruby-trunk - Feature #7546][Open] Change behavior of `Array#slice` for an argument of `Range` class

Posted by alexeymuranov (Alexey Muranov) (Guest)
on 2012-12-11 17:23
(Received via mailing list)
Issue #7546 has been reported by alexeymuranov (Alexey Muranov).

----------------------------------------
Feature #7546: Change behavior of `Array#slice` for an argument of 
`Range` class
https://bugs.ruby-lang.org/issues/7546

Author: alexeymuranov (Alexey Muranov)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version:


=begin
This is a concrete proposal to "fix" #4541.

It is also related to #7545.
For this proposal to make good sense, i think it would be nice if #7545 
was at least partially accepted.

=== Main proposal

I propose (({Array#slice})) with (({Range})) type argument to work as 
follows:

  a = ['0', '1', '2', '3']
  a[1..2]   # => ['1', '2']
  a[-2..-1] # => ['2', '3']
  a[2..1]   # => ['2', '1']
  a[-1..-2] # => ['3', '2']
  a[-1..1]  # => ['3', '0', '1']
  a[1..-1]  # => ['1', '0', '3']
  a[1..1]   # => ['1']
  a[1...1]  # => []
  a[4..4]   # => [nil]
  a[4...4]  # => []
  a[9..9]   # => [nil]
  a[9...9]  # => []
  a[1..5]   # => ['1', '2', '3', nil, nil]

=== Secondary proposal: consider adding new instance methods to 
(({Array})) to compensate the changed behavior of (({Array#slice}))

If this proposal is accepted, the code "(({a[1..-2]}))" for an array 
(({a})) will not work as before.
This can be compensated by adding new instance methods to (({Array})).
For example the following ones.

1. (({Array#clip(fixnum, fixnum)})):

  ['0', '1', '2', '3'].clip(1, 1) # => ['1', '2']

Thus (({a.clip(1, 1)})) would be a replacement for (({a[1..-2]})).

(It looks strange to have to convert a pair of numbers ((*m*)) and 
((*n*)) into a range (({m..(-1-n)})) to simply ask an array to remove 
((*m*)) elements from the beginning and ((*n*)) elements from the end.
If #7545 is accepted, then the "(({a[1..-2]}))" syntax for "clipping" an 
array will make not much sense and maybe will not be possible.)

2. (({Array#from(fixnum)})), (({Array#till(fixnum)})):

  a = ['0', '1', '2', '3']
  a.from(1)          # => ['1', '2', '3']
  a.till(1)          # => ['0', '1']
  a.from(1).till(-2) # => ['1', '2']

In fact, in ((*Rails*)) (({ActiveSupport})) there are methods 
(({Array#from})) and (({Array#to})) like this, but unfortunately they do 
not accept negative indices.

((*Remark*)).  It would also be possible to have (({Array#clip!})), 
(({Array#from!})), (({Array#till!})).
=end
Posted by drbrain (Eric Hodel) (Guest)
on 2012-12-11 17:51
(Received via mailing list)
Issue #7546 has been updated by drbrain (Eric Hodel).

Target version set to Next Major

This will break existing code so I set it to next major.
----------------------------------------
Feature #7546: Change behavior of `Array#slice` for an argument of 
`Range` class
https://bugs.ruby-lang.org/issues/7546#change-34627

Author: alexeymuranov (Alexey Muranov)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version: Next Major


=begin
This is a concrete proposal to "fix" #4541.

It is also related to #7545.
For this proposal to make good sense, i think it would be nice if #7545 
was at least partially accepted.

=== Main proposal

I propose (({Array#slice})) with (({Range})) type argument to work as 
follows:

  a = ['0', '1', '2', '3']
  a[1..2]   # => ['1', '2']
  a[-2..-1] # => ['2', '3']
  a[2..1]   # => ['2', '1']
  a[-1..-2] # => ['3', '2']
  a[-1..1]  # => ['3', '0', '1']
  a[1..-1]  # => ['1', '0', '3']
  a[1..1]   # => ['1']
  a[1...1]  # => []
  a[4..4]   # => [nil]
  a[4...4]  # => []
  a[9..9]   # => [nil]
  a[9...9]  # => []
  a[1..5]   # => ['1', '2', '3', nil, nil]

=== Secondary proposal: consider adding new instance methods to 
(({Array})) to compensate the changed behavior of (({Array#slice}))

If this proposal is accepted, the code "(({a[1..-2]}))" for an array 
(({a})) will not work as before.
This can be compensated by adding new instance methods to (({Array})).
For example the following ones.

1. (({Array#clip(fixnum, fixnum)})):

  ['0', '1', '2', '3'].clip(1, 1) # => ['1', '2']

Thus (({a.clip(1, 1)})) would be a replacement for (({a[1..-2]})).

(It looks strange to have to convert a pair of numbers ((*m*)) and 
((*n*)) into a range (({m..(-1-n)})) to simply ask an array to remove 
((*m*)) elements from the beginning and ((*n*)) elements from the end.
If #7545 is accepted, then the "(({a[1..-2]}))" syntax for "clipping" an 
array will make not much sense and maybe will not be possible.)

2. (({Array#from(fixnum)})), (({Array#till(fixnum)})):

  a = ['0', '1', '2', '3']
  a.from(1)          # => ['1', '2', '3']
  a.till(1)          # => ['0', '1']
  a.from(1).till(-2) # => ['1', '2']

In fact, in ((*Rails*)) (({ActiveSupport})) there are methods 
(({Array#from})) and (({Array#to})) like this, but unfortunately they do 
not accept negative indices.

((*Remark*)).  It would also be possible to have (({Array#clip!})), 
(({Array#from!})), (({Array#till!})).
=end
Posted by marcandre (Marc-Andre Lafortune) (Guest)
on 2012-12-11 20:29
(Received via mailing list)
Issue #7546 has been updated by marcandre (Marc-Andre Lafortune).

Assignee set to matz (Yukihiro Matsumoto)

-5 from me:

* this doesn't solve any real-life problem I can think of

* it will introduce incompatibilities

* those incompatibilities would be very difficult to find by code 
review/grep/whatever

* this would make `array[42..n]` not always the same as 
`array[42...n+1]`

* what about String#slice?

The goal is not to invent a new language.

----------------------------------------
Feature #7546: Change behavior of `Array#slice` for an argument of 
`Range` class
https://bugs.ruby-lang.org/issues/7546#change-34632

Author: alexeymuranov (Alexey Muranov)
Status: Open
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: core
Target version: Next Major


=begin
This is a concrete proposal to "fix" #4541.

It is also related to #7545.
For this proposal to make good sense, i think it would be nice if #7545 
was at least partially accepted.

=== Main proposal

I propose (({Array#slice})) with (({Range})) type argument to work as 
follows:

  a = ['0', '1', '2', '3']
  a[1..2]   # => ['1', '2']
  a[-2..-1] # => ['2', '3']
  a[2..1]   # => ['2', '1']
  a[-1..-2] # => ['3', '2']
  a[-1..1]  # => ['3', '0', '1']
  a[1..-1]  # => ['1', '0', '3']
  a[1..1]   # => ['1']
  a[1...1]  # => []
  a[4..4]   # => [nil]
  a[4...4]  # => []
  a[9..9]   # => [nil]
  a[9...9]  # => []
  a[1..5]   # => ['1', '2', '3', nil, nil]

=== Secondary proposal: consider adding new instance methods to 
(({Array})) to compensate the changed behavior of (({Array#slice}))

If this proposal is accepted, the code "(({a[1..-2]}))" for an array 
(({a})) will not work as before.
This can be compensated by adding new instance methods to (({Array})).
For example the following ones.

1. (({Array#clip(fixnum, fixnum)})):

  ['0', '1', '2', '3'].clip(1, 1) # => ['1', '2']

Thus (({a.clip(1, 1)})) would be a replacement for (({a[1..-2]})).

(It looks strange to have to convert a pair of numbers ((*m*)) and 
((*n*)) into a range (({m..(-1-n)})) to simply ask an array to remove 
((*m*)) elements from the beginning and ((*n*)) elements from the end.
If #7545 is accepted, then the "(({a[1..-2]}))" syntax for "clipping" an 
array will make not much sense and maybe will not be possible.)

2. (({Array#from(fixnum)})), (({Array#till(fixnum)})):

  a = ['0', '1', '2', '3']
  a.from(1)          # => ['1', '2', '3']
  a.till(1)          # => ['0', '1']
  a.from(1).till(-2) # => ['1', '2']

In fact, in ((*Rails*)) (({ActiveSupport})) there are methods 
(({Array#from})) and (({Array#to})) like this, but unfortunately they do 
not accept negative indices.

((*Remark*)).  It would also be possible to have (({Array#clip!})), 
(({Array#from!})), (({Array#till!})).
=end
Posted by alexeymuranov (Alexey Muranov) (Guest)
on 2012-12-11 22:04
(Received via mailing list)
Issue #7546 has been updated by alexeymuranov (Alexey Muranov).


marcandre (Marc-Andre Lafortune) wrote:

> * this doesn't solve any real-life problem I can think of

For me it solves one: the current behavior does not make sense to me, or 
i do not understand which abstract object is modeled by `Range` :).

> * this would make `array[42..n]` not always the same as `array[42...n+1]`

for n ≥ 42 it should be the same, otherwise i propose to consider #7545.

> * what about String#slice?

The same.

By the way, why would you slice a 5-element array or a 5-letter string 
by something like 2..42 ?
----------------------------------------
Feature #7546: Change behavior of `Array#slice` for an argument of 
`Range` class
https://bugs.ruby-lang.org/issues/7546#change-34635

Author: alexeymuranov (Alexey Muranov)
Status: Open
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: core
Target version: Next Major


=begin
This is a concrete proposal to "fix" #4541.

It is also related to #7545.
For this proposal to make good sense, i think it would be nice if #7545 
was at least partially accepted.

=== Main proposal

I propose (({Array#slice})) with (({Range})) type argument to work as 
follows:

  a = ['0', '1', '2', '3']
  a[1..2]   # => ['1', '2']
  a[-2..-1] # => ['2', '3']
  a[2..1]   # => ['2', '1']
  a[-1..-2] # => ['3', '2']
  a[-1..1]  # => ['3', '0', '1']
  a[1..-1]  # => ['1', '0', '3']
  a[1..1]   # => ['1']
  a[1...1]  # => []
  a[4..4]   # => [nil]
  a[4...4]  # => []
  a[9..9]   # => [nil]
  a[9...9]  # => []
  a[1..5]   # => ['1', '2', '3', nil, nil]

=== Secondary proposal: consider adding new instance methods to 
(({Array})) to compensate the changed behavior of (({Array#slice}))

If this proposal is accepted, the code "(({a[1..-2]}))" for an array 
(({a})) will not work as before.
This can be compensated by adding new instance methods to (({Array})).
For example the following ones.

1. (({Array#clip(fixnum, fixnum)})):

  ['0', '1', '2', '3'].clip(1, 1) # => ['1', '2']

Thus (({a.clip(1, 1)})) would be a replacement for (({a[1..-2]})).

(It looks strange to have to convert a pair of numbers ((*m*)) and 
((*n*)) into a range (({m..(-1-n)})) to simply ask an array to remove 
((*m*)) elements from the beginning and ((*n*)) elements from the end.
If #7545 is accepted, then the "(({a[1..-2]}))" syntax for "clipping" an 
array will make not much sense and maybe will not be possible.)

2. (({Array#from(fixnum)})), (({Array#till(fixnum)})):

  a = ['0', '1', '2', '3']
  a.from(1)          # => ['1', '2', '3']
  a.till(1)          # => ['0', '1']
  a.from(1).till(-2) # => ['1', '2']

In fact, in ((*Rails*)) (({ActiveSupport})) there are methods 
(({Array#from})) and (({Array#to})) like this, but unfortunately they do 
not accept negative indices.

((*Remark*)).  It would also be possible to have (({Array#clip!})), 
(({Array#from!})), (({Array#till!})).
=end
Posted by Matthew Kerwin (mattyk)
on 2012-12-11 22:27
(Received via mailing list)
Issue #7546 has been updated by phluid61 (Matthew Kerwin).


alexeymuranov (Alexey Muranov) wrote:
> marcandre (Marc-Andre Lafortune) wrote:
>
> > * this doesn't solve any real-life problem I can think of
>
> For me it solves one: the current behavior does not make sense to me, or i do 
not understand which abstract object is modeled by `Range` :).

At the risk of sounding glib, there is an alternative solution: learn 
it.
----------------------------------------
Feature #7546: Change behavior of `Array#slice` for an argument of 
`Range` class
https://bugs.ruby-lang.org/issues/7546#change-34636

Author: alexeymuranov (Alexey Muranov)
Status: Open
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: core
Target version: Next Major


=begin
This is a concrete proposal to "fix" #4541.

It is also related to #7545.
For this proposal to make good sense, i think it would be nice if #7545 
was at least partially accepted.

=== Main proposal

I propose (({Array#slice})) with (({Range})) type argument to work as 
follows:

  a = ['0', '1', '2', '3']
  a[1..2]   # => ['1', '2']
  a[-2..-1] # => ['2', '3']
  a[2..1]   # => ['2', '1']
  a[-1..-2] # => ['3', '2']
  a[-1..1]  # => ['3', '0', '1']
  a[1..-1]  # => ['1', '0', '3']
  a[1..1]   # => ['1']
  a[1...1]  # => []
  a[4..4]   # => [nil]
  a[4...4]  # => []
  a[9..9]   # => [nil]
  a[9...9]  # => []
  a[1..5]   # => ['1', '2', '3', nil, nil]

=== Secondary proposal: consider adding new instance methods to 
(({Array})) to compensate the changed behavior of (({Array#slice}))

If this proposal is accepted, the code "(({a[1..-2]}))" for an array 
(({a})) will not work as before.
This can be compensated by adding new instance methods to (({Array})).
For example the following ones.

1. (({Array#clip(fixnum, fixnum)})):

  ['0', '1', '2', '3'].clip(1, 1) # => ['1', '2']

Thus (({a.clip(1, 1)})) would be a replacement for (({a[1..-2]})).

(It looks strange to have to convert a pair of numbers ((*m*)) and 
((*n*)) into a range (({m..(-1-n)})) to simply ask an array to remove 
((*m*)) elements from the beginning and ((*n*)) elements from the end.
If #7545 is accepted, then the "(({a[1..-2]}))" syntax for "clipping" an 
array will make not much sense and maybe will not be possible.)

2. (({Array#from(fixnum)})), (({Array#till(fixnum)})):

  a = ['0', '1', '2', '3']
  a.from(1)          # => ['1', '2', '3']
  a.till(1)          # => ['0', '1']
  a.from(1).till(-2) # => ['1', '2']

In fact, in ((*Rails*)) (({ActiveSupport})) there are methods 
(({Array#from})) and (({Array#to})) like this, but unfortunately they do 
not accept negative indices.

((*Remark*)).  It would also be possible to have (({Array#clip!})), 
(({Array#from!})), (({Array#till!})).
=end
Posted by alexeymuranov (Alexey Muranov) (Guest)
on 2012-12-12 22:37
(Received via mailing list)
Issue #7546 has been updated by alexeymuranov (Alexey Muranov).


=begin
In fact, i do not request particularly this part:

  a = ['0', '1', '2', '3']
  a[4..4]   # => [nil]
  a[4...4]  # => []
  a[9..9]   # => [nil]
  a[9...9]  # => []
  a[1..5]   # => ['1', '2', '3', nil, nil]

The following alternative, closer to the current behavior, would be fine 
with me:

  a = ['0', '1', '2', '3']
  a[4..4]   # => []
  a[4...4]  # => []
  a[9..9]   # => []
  a[9...9]  # => []
  a[1..5]   # => ['1', '2', '3']
=end

----------------------------------------
Feature #7546: Change behavior of `Array#slice` for an argument of 
`Range` class
https://bugs.ruby-lang.org/issues/7546#change-34677

Author: alexeymuranov (Alexey Muranov)
Status: Open
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: core
Target version: Next Major


=begin
This is a concrete proposal to "fix" #4541.

It is also related to #7545.
For this proposal to make good sense, i think it would be nice if #7545 
was at least partially accepted.

=== Main proposal

I propose (({Array#slice})) with (({Range})) type argument to work as 
follows:

  a = ['0', '1', '2', '3']
  a[1..2]   # => ['1', '2']
  a[-2..-1] # => ['2', '3']
  a[2..1]   # => ['2', '1']
  a[-1..-2] # => ['3', '2']
  a[-1..1]  # => ['3', '0', '1']
  a[1..-1]  # => ['1', '0', '3']
  a[1..1]   # => ['1']
  a[1...1]  # => []
  a[4..4]   # => [nil]
  a[4...4]  # => []
  a[9..9]   # => [nil]
  a[9...9]  # => []
  a[1..5]   # => ['1', '2', '3', nil, nil]

=== Secondary proposal: consider adding new instance methods to 
(({Array})) to compensate the changed behavior of (({Array#slice}))

If this proposal is accepted, the code "(({a[1..-2]}))" for an array 
(({a})) will not work as before.
This can be compensated by adding new instance methods to (({Array})).
For example the following ones.

1. (({Array#clip(fixnum, fixnum)})):

  ['0', '1', '2', '3'].clip(1, 1) # => ['1', '2']

Thus (({a.clip(1, 1)})) would be a replacement for (({a[1..-2]})).

(It looks strange to have to convert a pair of numbers ((*m*)) and 
((*n*)) into a range (({m..(-1-n)})) to simply ask an array to remove 
((*m*)) elements from the beginning and ((*n*)) elements from the end.
If #7545 is accepted, then the "(({a[1..-2]}))" syntax for "clipping" an 
array will make not much sense and maybe will not be possible.)

2. (({Array#from(fixnum)})), (({Array#till(fixnum)})):

  a = ['0', '1', '2', '3']
  a.from(1)          # => ['1', '2', '3']
  a.till(1)          # => ['0', '1']
  a.from(1).till(-2) # => ['1', '2']

In fact, in ((*Rails*)) (({ActiveSupport})) there are methods 
(({Array#from})) and (({Array#to})) like this, but unfortunately they do 
not accept negative indices.

((*Remark*)).  It would also be possible to have (({Array#clip!})), 
(({Array#from!})), (({Array#till!})).
=end
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.