Why Array # slice and array # slice! behave differently?

I could not understand why, in Ruby, Array#slice and Array#slice! behave differently than Array#sort and Array#sort! (as one returns the results in a new array, and the other works on the current object).

With sort first (without a break) returns a sorted copy of the current array, and sort! sorts the current array.

slice returns an array with the specified range, and slice! removes the specified range from the current object.

What is the reason Array#slice! behaves like this, instead of making the current Array object with the specified range?

Example:

 a = [0,1,2,3,4,5,6,7,8,9] b = a.slice( 2,2 ) puts "slice:" puts " a = " + a.inspect puts " b = " + b.inspect b = a.slice!(2,2) puts "slice!:" puts " a = " + a.inspect puts " b = " + b.inspect 

Output:

 slice: a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] b = [2, 3] slice!: a = [0, 1, 4, 5, 6, 7, 8, 9] b = [2, 3] 

http://ideone.com/77xFva

+7
ruby behavior design-decisions
source share
3 answers

#slice and #slice! the behavior is equivalent: both "return a subarray, starting at the starting index and continuing for elements of length", just like #sort and #sort! return a sorted array or #reverse and #reverse! returns an inverse array.

The difference is that bang methods also modify the object itself.

 a = [4,2,6,9,1,5,8] b = a.dup a.sort == b.sort! # => true a == b # => false b = a.dup a.reverse == b.reverse! # => true a == b # => false b = a.dup a.slice(2,2) == b.slice!(2,2) # => true a == b # => false 
+3
source share

! or bang methods in ruby ​​usually mutate an existing object, rather than the equivalent of a non-bang method that returns a new object. If you want to modify an existing object, use the bang method parameter.

EDIT: to solve the design decision, I'm not Matz, but I'm going to assume that since the character of slice is to return a subset, it returns a subset in each case. For other bang methods like gsub or sort , you modify (potentially) the entire string / object so that it either returns a copy or returns the original with the changes.

+1
source share

I think the idea of ​​the design solution is that if you call Array#slice! , then you already have a pointer to the slice of the array (provided that you assigned it to a variable). The logical solution is to modify the object, so the slice is no longer in the original array.

You can see how this would be useful in a loop, for example. If you want to save a slice of the first three elements of the array, do something with these three elements and stop when they are no more, you can use Array#slice! , and this will eventually destroy the array.

Now, if you imagine that the array from the example is a queue or a stack, it will be clear why you want to delete parts of the array.

0
source share

All Articles