Renvoie au moins deux valeurs d'une méthode


105

Existe-t-il une possibilité de renvoyer plusieurs valeurs de la méthode? Quelque chose comme ça:

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

[a, b, c] = someMethod

Réponses:


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

Vous devez utiliser la mise en forme du code, pas la mise en forme du texte. Indentez les lignes de quatre espaces et la bizarrerie causée par l' >>invite d'irb disparaîtra.
Chris Lutz

4
Puisqu'un retour explicite est considéré comme Ruby non idiomatique, vous pouvez également utiliser un retour implicite en mettant explicitement les valeurs de retour dans une liste:def foo_and_bar; ['foo', 'bar']; end
Dennis

43

Ruby a une forme limitée de liaison de déstructuration:

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

Il a également une forme limitée de liaison structurante:

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

Vous pouvez combiner ces deux formes comme ceci:

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

Il y a plusieurs autres choses que vous pouvez faire avec la liaison de déstructuration / structuration. Je n'ai pas montré en utilisant l'opérateur splat ( *) sur le côté droit. Je n'ai pas montré de nidification (en utilisant des paranthèses). Je n'ai pas montré que vous pouvez utiliser la liaison de déstructuration dans la liste des paramètres d'un bloc ou d'une méthode.

Voici juste un apéritif:

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

Bien que renvoyer plusieurs valeurs soit souvent utile, je trouve généralement que c'est un pointeur vers une nouvelle exigence d'objet.

Autrement dit, je trouve généralement que ces valeurs de retour sont étroitement liées entre elles dans le sens / le contexte et sont transmises en tant que telles. Donc, dans ces cas, je créerais un nouvel objet pour les lier ensemble. C'est une odeur de code particulière que j'ai appris à reconnaître.


4
plus de liberté, plus de responsabilité. Un rubisiste expérimenté en profiterait et écrirait de beaux codes. tandis que les recrues rubis peuvent aggraver les choses.
fengd

1
Ce n'est clairement pas toujours le cas, sinon des choses comme chunkn'existeraient pas. Excellent principe cependant. Code odeur en effet. Rock On.
Darth Egregious

6

Vous pouvez également y parvenir en renvoyant un tableau, comme

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

qui semble fonctionnellement équivalent à

def sumdiff(x, y)
    return x+y, x-y
end
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.