27 votes

Des façons élégantes de renvoyer plusieurs valeurs d'une fonction

Il semble que dans la plupart des langages de programmation grand public, retourner plusieurs valeurs à partir d'une fonction est extrêmement maladroit chose.

Les solutions classiques sont à effectuer soit une structure ou un simple vieux de données de classe et de retour, ou de passer au moins certains des paramètres par référence ou un pointeur au lieu de les renvoyer.

À l'aide de références/pointeurs est assez gênant car il s'appuie sur les effets secondaires et les moyens que vous avez encore un autre paramètre à passer.

La class/struct solution est d'ailleurs à mon humble avis assez maladroite parce qu'alors vous retrouver avec un million de petites classes et/ou des structures qui ne sont utilisés que pour les valeurs de retour des fonctions, générant inutiles, et le niveau de verbosité.

En outre, un grand nombre de fois, il y a une valeur de retour qui est toujours nécessaire, et le reste ne sont utilisés que par l'appelant dans certaines circonstances. Aucune de ces solutions permet à l'appelant d'ignorer inutiles types de retour.

La seule langue que je suis conscient de qui gère plusieurs valeurs de retour élégante est Python. Pour ceux d'entre vous qui ne connaissent pas, il utilise tuple déballage:

a, b = foo(c)  # a and b are regular variables.
myTuple = foo(c)  # myTuple is a tuple of (a, b)

Quelqu'un aurait-il d'autres solutions à ce problème? Les deux idiomes que les travaux existant dans les principaux langages en plus de Python et de la langue au niveau des solutions que vous avez vu dans la non-intégrer les langues sont les bienvenues.

24voto

user21714 Points 3596

Presque toutes les langues fonctionnelles influencées par ML (qui sont la plupart d'entre elles) ont également un excellent support de tuple qui rend ce genre de chose trivial.

Pour C ++ j'aime boost :: tuple plus boost :: tie (ou std :: tr1 si vous l'avez)

 typedef boost::tuple<double,double,double> XYZ;

XYZ foo();

double x,y,z;
boost::tie(x,y,z) = foo();
 

ou un exemple moins artificiel

 MyMultimap::iterator lower,upper;
boost::tie(lower,upper) = some_map.equal_range(key);
 

9voto

Moss Collum Points 1316

Quelques langues, notamment Lisp et JavaScript, ont une fonction appelée déstructuration de cession ou de la déstructuration lier. Il s'agit essentiellement d'un tuple de déballage sur les stéroïdes: plutôt que d'être limité à des séquences comme les tuples, listes, ou des générateurs, vous pouvez décompresser en plus complexes structures d'objets dans une instruction d'affectation. Pour plus de détails, voir ici pour la version Lisp ou ici pour la (plutôt plus lisible) version JavaScript.

Autre que cela, je ne sais pas de nombreuses fonctionnalités de langage pour faire face à de multiples valeurs de retour en général. Cependant, il ya quelques usages spécifiques de plusieurs valeurs de retour qui peuvent souvent être remplacés par d'autres fonctions du langage. Par exemple, si une des valeurs est un code d'erreur, il peut être remplacé avec une exception.

Lors de la création de nouvelles classes pour contenir plusieurs valeurs de retour se sent comme l'encombrement, le fait que vous êtes de retour de ces valeurs est souvent un signe que votre code sera mieux en général une fois que la classe est créée. En particulier, les autres fonctions qui traitent les mêmes données peuvent ensuite passer à la nouvelle classe, ce qui peut rendre votre code plus facile à suivre. Ce n'est pas toujours vrai, mais il vaut la peine de considérer. (Cpeterso réponse sur les données touffes exprime cela plus en détail).

7voto

Evan Fosmark Points 17732

Exemple PHP:

 function my_funct() {
    $x = "hello";
    $y = "world";
    return array($x, $y);
}
 

Ensuite, lors de l'exécution:

 list($x, $y) = my_funct();
echo $x.' '.$y; // "hello world"
 

5voto

Chris Peterson Points 1726

Si une fonction retourne plusieurs valeurs, ce qui est un signe que vous pourriez être témoin de la "les Données de la Touffe" odeur de code. Souvent les données, les touffes sont des valeurs primitives que personne ne pense à se transformer en un objet, mais des choses intéressantes qui se passe, lorsque vous commencez à regarder pour le comportement de déménager dans les nouveaux objets.

L'écriture minuscule classes d'assistance peut être saisie de texte supplémentaire, mais il fournit des noms clairs et vérification de type fort. Les développeurs de l'entretien de votre code vous en seront reconnaissants. Et utile de petites classes souvent grandir pour être utilisé dans un autre code.

Aussi, si une fonction retourne plusieurs valeurs, alors il pourrait être en train de faire trop de travail. Pourrait la fonction d'être remaniée en deux (ou plus) des petites fonctions?

4voto

Glomek Points 12183

Personne ne semble avoir encore mentionné Perl.

 sub myfunc {
  return 1, 2;
}
my($val1, $val2) = myfunc();
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X