Kembalikan dua atau lebih nilai dari sebuah metode

105

Apakah ada kemungkinan untuk mengembalikan beberapa nilai dari metode? Sesuatu seperti ini:

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

[a, b, c] = someMethod
demas
sumber

Jawaban:

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
Aditya Mukherji
sumber
Anda harus menggunakan format kode, bukan format teks. Indentasi baris empat spasi dan keanehan yang disebabkan oleh >>prompt irb akan hilang.
Chris Lutz
4
Karena pengembalian eksplisit dianggap Ruby non-idiomatik, Anda juga dapat menggunakan pengembalian implisit dengan secara eksplisit meletakkan nilai yang dikembalikan dalam daftar:def foo_and_bar; ['foo', 'bar']; end
Dennis
43

Ruby memiliki bentuk destructuring bind yang terbatas:

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

Ini juga memiliki bentuk penataan ikatan yang terbatas:

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

Anda dapat menggabungkan kedua bentuk tersebut seperti ini:

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

Ada beberapa hal lain yang dapat Anda lakukan dengan destructuring / structuring bind. Saya tidak menunjukkan menggunakan operator percikan ( *) di sisi kanan. Saya tidak menunjukkan bersarang (menggunakan tanda kurung). Saya tidak menunjukkan bahwa Anda dapat menggunakan destructuring bind dalam daftar parameter dari sebuah blok atau metode.

Ini hanya makanan pembuka:

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]
Jörg W Mittag
sumber
16

Meskipun mengembalikan beberapa nilai sering kali berguna, saya biasanya menganggapnya sebagai penunjuk ke persyaratan objek baru.

Artinya, saya biasanya menemukan bahwa nilai-nilai kembali itu terkait erat dalam makna / konteks dan diteruskan seperti itu. Jadi dalam kasus ini saya akan membuat objek baru untuk mengikat ini bersama-sama. Ini adalah bau kode tertentu yang telah saya pelajari untuk dikenali.

Brian Agnew
sumber
4
lebih banyak kebebasan, lebih banyak tanggung jawab. Rubyist berpengalaman akan memanfaatkannya dan menulis beberapa kode yang indah. sementara pemula ruby ​​bisa memperburuk keadaan.
fengd
1
Jelas itu tidak selalu terjadi, atau hal-hal seperti chunkitu tidak akan ada. Prinsip yang sangat baik. Kode memang berbau. Teruskan.
Darth Egregious
6

Anda juga dapat mencapai ini mengembalikan larik, seperti

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

yang tampaknya secara fungsional setara dengan

def sumdiff(x, y)
    return x+y, x-y
end
Zack Xu
sumber