Chaque fois que j'échange des valeurs dans un tableau, je m'assure que j'ai stocké l'une des valeurs dans une variable de référence. Mais j'ai trouvé que Ruby peut renvoyer deux valeurs et échanger automatiquement deux valeurs. Par exemple,
array = [1, 3, 5 , 6 ,7]
array[0], array[1] = array[1] , array[0] #=> [3, 1]
Je me demandais comment Ruby faisait cela.
Réponses:
Contrairement à d'autres langages, la valeur de retour de tout appel de méthode dans Ruby est toujours un objet. Cela est possible car, comme tout dans Ruby,
nil
lui-même est un objet.Vous verrez trois modèles de base. Ne renvoyant aucune valeur particulière:
Renvoyer une valeur singulière:
Cela correspond à ce que vous attendez des autres langages de programmation.
Les choses deviennent un peu différentes lorsqu'il s'agit de plusieurs valeurs de retour. Ceux-ci doivent être spécifiés explicitement:
Lorsque vous effectuez un appel qui renvoie plusieurs valeurs, vous pouvez les diviser en variables indépendantes:
Cette stratégie fonctionne également pour les types de substitution dont vous parlez:
la source
[1, 2]
et cela fonctionnera de la même manière que vos exemples ci-dessus.1,2
par lui-même est invalide, mais soit dereturn 1,2
ou de[1,2]
travail.Non, Ruby ne prend pas en charge le retour de deux objets. (BTW: vous renvoyez des objets, pas des variables. Plus précisément, vous renvoyez des pointeurs vers des objets.)
Cependant, il prend en charge l'affectation parallèle. Si vous avez plusieurs objets sur le côté droit d'une affectation, les objets sont rassemblés dans un
Array
:Si vous avez plus d'une "cible" (variable ou méthode de définition) sur le côté gauche d'une affectation, les variables sont liées aux éléments d'un
Array
sur le côté droit:Si le côté droit n'est pas un
Array
, il sera converti en un à l'aide de lato_ary
méthodeEt si nous mettons les deux ensemble, nous obtenons cela
L'opérateur splat sur le côté gauche d'une affectation est lié à cela. Cela signifie "prendre tous les éléments de gauche sur le
Array
côté droit":Enfin, les affectations parallèles peuvent être imbriquées en utilisant des parenthèses:
Lorsque vous
return
utilisez une méthode ounext
oubreak
un bloc, Ruby traitera ce genre de chose comme le côté droit d'une affectation, doncÀ propos, cela fonctionne également dans les listes de paramètres de méthodes et de blocs (les méthodes étant plus strictes et les blocs moins stricts):
Les blocs étant "moins stricts", c'est par exemple ce qui fait
Hash#each
fonctionner. Il s'agit en fait d'yield
un seul élément à deux élémentsArray
clé et valeur du bloc, mais nous écrivons généralementau lieu de
la source
tadman et Jörg W Mittag connaissent Ruby mieux que moi, et leurs réponses ne sont pas fausses, mais je ne pense pas qu'ils répondent à ce que OP voulait savoir. Je pense que la question n’était pas claire cependant. À mon avis, ce que OP voulait demander n'a rien à voir avec le renvoi de plusieurs valeurs.
La vraie question est, lorsque vous voulez changer les valeurs de deux variables
a
etb
(ou deux positions dans un tableau comme dans la question d'origine), pourquoi n'est-il pas nécessaire d'utiliser une variable temporelletemp
comme:mais peut être fait directement comme:
La réponse est que dans l'assignation multiple, tout le côté droit est évalué avant l'assignation de tout le côté gauche, et cela ne se fait pas un par un. Donc
a, b = b, a
n'est pas équivalent àa = b; b = a
.Évaluer d'abord tout le côté droit avant l'assignation est une nécessité qui découle de l'ajustement lorsque les deux côtés
=
ont des nombres de termes différents, et la description de Jörg W Mittag peut être indirectement liée à cela, mais ce n'est pas le problème principal.la source
Les tableaux sont une bonne option si vous n'avez que quelques valeurs. Si vous voulez plusieurs valeurs de retour sans avoir à connaître (et être confondu par) l'ordre des résultats, une alternative serait de retourner un Hash qui contient les valeurs nommées que vous voulez.
par exemple
la source