Ruby如何返回两个值?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (28)

每当我交换数组中的值时,我确保将其中一个值存储在引用变量中。但是我发现Ruby可以返回两个值并自动交换两个值。例如,

array = [1, 3, 5 , 6 ,7]
array[0], array[1] = array[1] , array[0] #=> [3, 1] 

我想知道Ruby如何做到这一点。

提问于
用户回答回答于

不,Ruby实际上不支持返回两个对象。(顺便说一句:你返回的是对象,而不是变量,更确切地说,你返回的是指向对象的指针。)

但是,它支持并行分配。如果在作业的右侧有多个对象,则将对象收集到Array

foo = 1, 2, 3
# is the same as
foo = [1, 2, 3]

如果在赋值的左侧有多个“目标”(变量或设置方法),变量将被绑定到Array右侧的元素:

a, b, c = ary
# is the same as
a = ary[0]
b = ary[1]
c = ary[2]

如果右侧不是 Array,它将使用该to_ary方法转换为一个

a, b, c = not_an_ary
# is the same as
ary = not_an_ary.to_ary
a = ary[0]
b = ary[1]
c = ary[2]

如果我们把它们放在一起,我们就可以得到它

a, b, c = d, e, f
# is the same as
ary = [d, e, f]
a = ary[0]
b = ary[1]
c = ary[2]

与此相关的是作业左侧的splat操作符。它的意思是“把所有剩下的元素Array放在右边”:

a, b, *c = ary
# is the same as
a = ary[0]
b = ary[1]
c = ary.drop(2) # i.e. the rest of the Array

最后但并非最不重要的一点,平行分配可以使用圆括号嵌套:

a, (b, c), d = ary
# is the same as
a = ary[0]
b, c = ary[1]
d = ary[2]
# which is the same as
a = ary[0]
b = ary[1][0]
c = ary[1][1]
d = ary[2]

当你return从一个方法或nextbreak从块或yield到块,红宝石将把这种-像一个分配的右手边,所以

return 1, 2
next 1, 2
break 1, 2
yield 1, 2
# is the same as
return [1, 2]
next [1, 2]
break [1, 2]
yield [1, 2]

顺便说一句,这也适用于方法和块的参数列表(方法更严格,块更不严格):

def foo(a, (b, c), d) p a, b, c, d end

bar {|a, (b, c), d| p a, b, c, d }

例如,“不那么严格”的块就是做什么的Hash#each。它实际上yield是一个单一的两元素Array的关键和价值块,但我们通常写

some_hash.each {|k, v| }

代替

some_hash.each {|(k, v)| }
用户回答回答于

与其他语言不同,Ruby中任何方法调用的返回值始终是一个对象。这是可能的,因为像Ruby中的所有内容一样,nil它本身就是一个对象。

你会看到三种基本模式。没有特别的价值:

def nothing
end

nothing
# => nil

返回一个奇异值:

def single
  1
end

x = single
# => 1

这符合你对其他编程语言的期望。

处理多个返回值时情况会有所不同。这些需要明确规定:

def multiple
  return 1, 2
end

x = multiple
# => [ 1, 2 ]
x
# => [ 1, 2 ]

在进行返回多个值的调用时,可以将它们分解为独立变量:

x, y = multiple
# => [ 1, 2 ]
x
# => 1
y
# => 2

这个策略也适用于你正在谈论的各种替代:

a, b = 1, 2
# => [1, 2]
a, b = b, a
# => [2, 1]
a
# => 2
b
# => 1

扫码关注云+社区