Повернути два та більше значення методу


105

Чи є можливість повернути кілька значень із методу? Щось на зразок цього:

def someMethod()
  return ["a", 10, SomeObject.new]
end

[a, b, c] = someMethod

Відповіді:


160
def sumdiff(x, y)
  return x+y, x-y
end
#=> nil

sumdiff(3, 4)
#=> [7, -1]

a = sumdiff(3,4)
#=> [7, -1]
a
#=> [7, -1]

a,b=sumdiff(3,4)
#=> [7, -1]
a
#=> 7
b
#=> -1

a,b,c=sumdiff(3,4)
#=> [7, -1]
a
#=> 7
b
#=> -1
c
#=> nil

Ви повинні використовувати форматування коду, а не форматування тексту. Відступи чотирьох пробілів і дивність, викликана підказом irb, >>відійдуть.
Кріс Лутц

4
Оскільки явне повернення вважається неідіоматичним Ruby, ви також можете використовувати неявне повернення, явно поклавши значення повернення у список:def foo_and_bar; ['foo', 'bar']; end
Деніс

43

Рубін має обмежену форму руйнування зв'язування:

ary = [1, 2, 3, 4]
a, b, c = ary
p a # => 1
p b # => 2
p c # => 3

a, b, *c = ary
p c # => [3, 4]

a, b, c, d, e = ary
p d # => 4
p e # => nil

Він також має обмежену форму структурування зв'язування:

 a = 1, 2, 3
 p a # => [1, 2, 3]

Ви можете комбінувати ці дві форми так:

a, b = b, a # Nice way to swap two variables

a, b = 1, 2, 3
p b # => 2

def foo; return 1, 2 end
a, b = foo
p a # => 1
p b # => 2

Є кілька інших речей, які ви можете зробити з руйнуванням / структуруванням зв'язування. Я не показав використання оператора splat ( *) праворуч. Я не показував гніздування (за допомогою парантезів). Я не показав, що ви можете використовувати destructuring bind у списку параметрів блоку чи методу.

Ось лише закуска:

def foo(((a, b, c, d), e, *f), g, *h)
  local_variables.sort.each do |lvar| puts "#{lvar} => #{eval(lvar).inspect}" end
end

foo([[1, 2, 3], 4, 5, 6], 7, 8, 9)
# a => 1
# b => 2
# c => 3
# d => nil
# e => 4
# f => [5, 6]
# g => 7
# h => [8, 9]

16

Хоча повернення декількох значень часто корисне, я зазвичай вважаю, що це вказівник на нову вимогу об'єкта.

Тобто я зазвичай вважаю, що ці повернені значення тісно пов'язані між собою за значенням / контекстом і передаються навколо як такі. Тож у цих випадках я створив би новий об'єкт, щоб зв'язати їх. Це особливий запах коду, який я навчився розпізнавати.


4
більше свободи, більше відповідальності. Досвідчений рубіст скористається цим і напише кілька красивих кодів. в той час як рубінові новички можуть погіршити ситуацію.
fengd

1
Ясно, що це не завжди так, інакше подібні речі chunkне існували б. Хоча відмінний принцип. Дійсно пахне кодом. Рок на.
Дарт Егрегійний

6

Ви також можете досягти цього повернення масиву, як

def sumdiff(x, y)
    [x+y, x-y]
end

що здається функціонально рівнозначним

def sumdiff(x, y)
    return x+y, x-y
end
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.