Não, Ruby na verdade não suporta o retorno de dois objetos. (BTW: você retorna objetos, não variáveis. Mais precisamente, você retorna ponteiros para objetos.)
No entanto, ele oferece suporte à atribuição paralela. Se você tiver mais de um objeto no lado direito de uma atribuição, os objetos serão coletados em Array
:
foo = 1, 2, 3
# is the same as
foo = [1, 2, 3]
Se você tiver mais de um "destino" (variável ou método setter) no lado esquerdo de uma atribuição, as variáveis serão vinculadas aos elementos de um Array
no lado direito:
a, b, c = ary
# is the same as
a = ary[0]
b = ary[1]
c = ary[2]
Se o lado direito não for um Array
, ele será convertido em um usando o to_ary
método
a, b, c = not_an_ary
# is the same as
ary = not_an_ary.to_ary
a = ary[0]
b = ary[1]
c = ary[2]
E se colocarmos os dois juntos, obtemos que
a, b, c = d, e, f
# is the same as
ary = [d, e, f]
a = ary[0]
b = ary[1]
c = ary[2]
Relacionado a isso está o operador splat no lado esquerdo de uma atribuição. Significa "pegar todos os elementos restantes Array
do lado direito":
a, b, *c = ary
# is the same as
a = ary[0]
b = ary[1]
c = ary.drop(2) # i.e. the rest of the Array
E por último, mas não menos importante, as atribuições paralelas podem ser aninhadas usando parênteses:
a, (b, c), d = ary
# is the same as
a = ary[0]
b, c = ary[1]
d = ary[2]
# which is the same as
a = ary[0]
b = ary[1][0]
c = ary[1][1]
d = ary[2]
Quando você return
a partir de um método ou next
ou break
de um bloco, Ruby vai tratar este tipo-de como o lado direito de uma atribuição, de modo
return 1, 2
next 1, 2
break 1, 2
# is the same as
return [1, 2]
next [1, 2]
break [1, 2]
A propósito, isso também funciona em listas de parâmetros de métodos e blocos (com métodos sendo mais estritos e blocos menos estritos):
def foo(a, (b, c), d) p a, b, c, d end
bar {|a, (b, c), d| p a, b, c, d }
Blocos sendo "menos rígidos" é, por exemplo, o que faz Hash#each
funcionar. Na verdade, é yield
um único elemento de doisArray
de de chave e valor para o bloco, mas geralmente escrevemos
some_hash.each {|k, v| }
ao invés de
some_hash.each {|(k, v)| }