Siempre que cambio valores en una matriz, me aseguro de almacenar uno de los valores en una variable de referencia. Pero descubrí que Ruby puede devolver dos valores, así como intercambiar automáticamente dos valores. Por ejemplo,
array = [1, 3, 5 , 6 ,7]
array[0], array[1] = array[1] , array[0] #=> [3, 1]
Me preguntaba cómo hace esto Ruby.
Respuestas:
A diferencia de otros lenguajes, el valor de retorno de cualquier llamada a método en Ruby es siempre un objeto. Esto es posible porque, como todo en Ruby, en
nil
sí mismo es un objeto.Hay tres patrones básicos que verá. Devolviendo ningún valor en particular:
Devolviendo un valor singular:
Esto está en línea con lo que esperaría de otros lenguajes de programación.
Las cosas se ponen un poco diferentes cuando se trata de múltiples valores de retorno. Estos deben especificarse explícitamente:
Al realizar una llamada que devuelve varios valores, puede dividirlos en variables independientes:
Esta estrategia también funciona para los tipos de sustitución de los que está hablando:
fuente
[1, 2]
y esto funcionará igual que los ejemplos anteriores.1,2
por sí solo no es válido, pero dereturn 1,2
o[1,2]
funciona.No, Ruby no admite la devolución de dos objetos. (Por cierto: devuelve objetos, no variables. Más precisamente, devuelve punteros a objetos).
Sin embargo, admite la asignación en paralelo. Si tiene más de un objeto en el lado derecho de una tarea, los objetos se recopilan en un
Array
:Si tiene más de un "objetivo" (variable o método de establecimiento) en el lado izquierdo de una asignación, las variables se unen a elementos de un
Array
en el lado derecho:Si el lado derecho no es un
Array
, se convertirá en uno usando elto_ary
métodoY si juntamos los dos, obtenemos eso
Relacionado con esto está el operador de símbolos en el lado izquierdo de una asignación. Significa "tomar todos los elementos sobrantes del
Array
lado derecho":Y por último, pero no menos importante, las asignaciones paralelas se pueden anidar usando paréntesis:
Cuando
return
a partir de un método onext
obreak
de un bloque, Ruby va a tratar este tipo de como el lado derecho de una asignación, por loPor cierto, esto también funciona en listas de parámetros de métodos y bloques (siendo los métodos más estrictos y los bloques menos estrictos):
Los bloques que son "menos estrictos" es, por ejemplo, lo que hace que
Hash#each
funcione. En realidad,yield
es un solo elementoArray
de dos claves y valor para el bloque, pero generalmente escribimosen vez de
fuente
tadman y Jörg W Mittag conocen a Ruby mejor que yo, y sus respuestas no son incorrectas, pero no creo que estén respondiendo lo que OP quería saber. Sin embargo, creo que la pregunta no estaba clara. Según tengo entendido, lo que OP quería preguntar no tiene nada que ver con devolver múltiples valores.
La pregunta real es, cuando desea cambiar los valores de dos variables
a
yb
(o dos posiciones en una matriz como en la pregunta original), ¿por qué no es necesario usar una variable temporaltemp
como:pero se puede hacer directamente como:
La respuesta es que en la asignación múltiple, todo el lado derecho se evalúa antes de asignar todo el lado izquierdo, y no se hace uno por uno. Entonces
a, b = b, a
no es equivalente aa = b; b = a
.Primero, evaluar todo el lado derecho antes de la asignación es una necesidad que se deriva del ajuste cuando ambos lados
=
tienen diferentes números de términos, y la descripción de Jörg W Mittag puede estar indirectamente relacionada con eso, pero ese no es el problema principal.fuente
Las matrices son una buena opción si solo tiene unos pocos valores. Si desea múltiples valores de retorno sin tener que saber (y confundirse por) el orden de los resultados, una alternativa sería devolver un Hash que contenga los valores con nombre que desee.
p.ej
fuente