Restituisce due e più valori da un metodo


105

È possibile restituire più valori dal metodo? Qualcosa come questo:

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

[a, b, c] = someMethod

Risposte:


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

È necessario utilizzare la formattazione del codice, non la formattazione del testo. Rientra le righe di quattro spazi e la stranezza causata dal >>prompt di irb scomparirà.
Chris Lutz

4
Poiché un ritorno esplicito è considerato Ruby non idiomatico, puoi anche usare un ritorno implicito inserendo esplicitamente i valori di ritorno in un elenco:def foo_and_bar; ['foo', 'bar']; end
Dennis

43

Ruby ha una forma limitata di legame destrutturante:

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

Ha anche una forma limitata di legame strutturante:

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

Puoi combinare queste due forme in questo modo:

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

Ci sono molte altre cose che puoi fare con il bind destrutturante / strutturante. Non ho mostrato l'utilizzo dell'operatore splat ( *) sul lato destro. Non ho mostrato la nidificazione (usando le parentesi). Non ho mostrato che puoi usare il bind destrutturante nell'elenco dei parametri di un blocco o metodo.

Ecco solo un antipasto:

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

Sebbene la restituzione di più valori sia spesso utile, di solito trovo che sia un puntatore a un nuovo requisito di oggetto.

Cioè, di solito trovo che quei valori di ritorno sono strettamente legati insieme nel significato / contesto e vengono trasmessi come tali. Quindi in questi casi creerei un nuovo oggetto per legarli insieme. È un particolare odore di codice che ho imparato a riconoscere.


4
più libertà, più responsabilità. Rubyist esperto ne trarrebbe vantaggio e scriverà dei bei codici. mentre i novellini rubino possono peggiorare le cose.
fengd

1
Beh, chiaramente non è sempre così, altrimenti cose del genere chunknon esisterebbero. Ottimo principio però. Il codice puzza davvero. Rock on.
Darth Egregious

6

Puoi ottenere ciò restituendo anche un array, come

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

che sembra funzionalmente equivalente a

def sumdiff(x, y)
    return x+y, x-y
end
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.