Ruby 为什么阵列#切片和阵列#切片!表现不同?

Ruby 为什么阵列#切片和阵列#切片!表现不同?,ruby,behavior,design-decisions,Ruby,Behavior,Design Decisions,我不明白为什么在Ruby中,Array#slice和Array#slice的行为不同于Array#sort和Array#sort(一个返回新数组的结果,另一个处理当前对象) 使用sort第一个数组(不带bang),返回当前数组的已排序副本,然后sort对当前数组进行排序 slice,返回具有指定范围的数组,然后slice从当前对象删除指定范围 数组#切片的原因是什么的行为与此类似,而不是使当前对象成为具有指定范围的数组 例如: a=[0,1,2,3,4,5,6,7,8,9] b=a.切片(2,2

我不明白为什么在Ruby中,
Array#slice
Array#slice的行为不同于
Array#sort
Array#sort(一个返回新数组的结果,另一个处理当前对象)

使用
sort
第一个数组(不带bang),返回当前数组的已排序副本,然后
sort对当前数组进行排序

slice
,返回具有指定范围的数组,然后
slice从当前对象删除指定范围

数组#切片的原因是什么的行为与此类似,而不是使当前对象成为具有指定范围的数组

例如:

a=[0,1,2,3,4,5,6,7,8,9]
b=a.切片(2,2)
放入“切片”:
将“a=”+a
放入“b=”+b
b=a.切片!(2,2)
放入“切片!”
将“a=”+a
放入“b=”+b
输出:

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]

或bang方法通常会改变现有对象,而不是返回新对象的非bang方法等价物。如果要修改现有对象,请使用“bang方法”选项

编辑: 为了解决设计决策问题,我不是Matz,但我想,因为
slice
的本质是返回一个子集,所以它在每种情况下都返回子集。对于其他bang方法,如
gsub
sort
,您正在(可能)修改整个字符串/对象,以便它返回一个副本或返回带有更改的原始字符串/对象。

#slice
#slice行为是等效的:两者都“返回从起始索引开始的子数组,并继续返回长度元素”,方法与
#sort
#sort相同
返回排序数组或
#reverse
#reverse返回一个反向数组

不同之处在于,bang方法也会修改对象本身

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

我认为设计决策背后的想法是,如果调用
Array#slice
那么您已经有了一个指向数组切片的指针(假设您将其分配给了一个变量)。合乎逻辑的决定是修改对象,使切片不再位于原始数组中

例如,您可以看到这在循环中是多么有用。如果您想继续获取数组前3个元素的切片,请对这3个元素执行某些操作,并在没有更多元素时停止,您可以使用
array#slice
最终会破坏阵列


现在,如果您假设示例中的数组是一个队列或堆栈,那么您可以理解为什么要删除部分数组。

这不是用户所要求的。他知道这一点,他在询问设计决策。具体来说,为什么要切片!不会用结果替换当前对象。@SimoneCarletti这可能有帮助吗?使用
没有设置行为,它只是指示该方法以某种方式改变输入,同时也具有完全相同的输出。您可以将它添加到您编写的任何方法的末尾。这不是用户要求的。他知道这一点,他在询问设计决策。具体来说,为什么要切片!不使用结果替换当前对象。
#slice
(和
#slice!
)“如果索引超出范围,则返回nil”。这种情况与用返回值替换对象的想法不一致,这可能是我迄今为止读过的最好的解释之一+1我不得不这么说=/我对bang方法的想法是错误的。