Ні, 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
від методу або next
або break
з блоку, Ruby буде ставитися до такого роду-о , як у правій частині присвоювання, так
return 1, 2
next 1, 2
break 1, 2
# is the same as
return [1, 2]
next [1, 2]
break [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)| }