Devuelve dos o más valores de un método

105

¿Existe la posibilidad de devolver varios valores del método? Algo como esto:

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

[a, b, c] = someMethod
demas
fuente

Respuestas:

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
fuente
Debe utilizar formato de código, no formato de texto. Sangre las líneas cuatro espacios y la rareza causada por el >>indicador de irb desaparecerá.
Chris Lutz
4
Dado que un retorno explícito se considera Ruby no idiomático, también puede utilizar un retorno implícito poniendo explícitamente los valores de retorno en una lista:def foo_and_bar; ['foo', 'bar']; end
Dennis
43

Ruby tiene una forma limitada de enlace de desestructuración:

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

También tiene una forma limitada de estructuración vinculante:

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

Puede combinar esas dos formas así:

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

Hay varias otras cosas que puede hacer con el enlace de desestructuración / estructuración. No mostré el uso del operador splat (* ) en el lado derecho. No mostré anidación (usando paréntesis). No mostré que se pueda usar el enlace de desestructuración en la lista de parámetros de un bloque o método.

Aquí hay solo un aperitivo:

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
fuente
16

Si bien devolver varios valores suele ser útil, generalmente encuentro que es un puntero a un nuevo requisito de objeto.

Es decir, generalmente encuentro que esos valores de retorno están estrechamente vinculados en significado / contexto y se transmiten como tales. Entonces, en estos casos, crearía un nuevo objeto para unirlos. Es un olor de código particular que he aprendido a reconocer.

Brian Agnew
fuente
4
más libertad, más responsabilidad. El rubyista experimentado lo aprovecharía y escribiría algunos códigos hermosos. mientras que los novatos rubí pueden empeorar las cosas.
fengd
1
Bueno, claramente ese no es siempre el caso, o de lo contrario chunkno existirían cosas así . Sin embargo, excelente principio. De hecho, huele a código. Rock on.
Darth Egregious
6

También puede lograr esto devolviendo una matriz, como

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

que parece funcionalmente equivalente a

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