Y a-t-il une raison pour laquelle les fonctions ne retournent qu'une seule valeur
Dans la plupart des langages de programmation ? Partagez vos avis

Le , par Stéphane le calme, Chroniqueur Actualités
Y a-t-il une raison pour laquelle les fonctions dans la plupart des langages de programmation, bien que supportant un grand nombre de paramètres en entrée, ne retournent qu’une seule valeur ? C’est la question qu’un développeur a posée sur le réseau Stack Exchange. Pour lui, même s’il est possible de contourner cette limitation (par exemple en retournant des pointeurs ou en définissant / retournant des structures / classes), il semble étrange que les langages n’aient pas été pensés pour supporter un retour de valeurs multiples d’une façon plus « naturelle ». Voici quelques-unes des réponses qui ont reçu le plus de votes favorables :

  • Certains langages, comme Python, supportent nativement un retour de valeurs multiples, tandis que certains autres, comme C#, ne les supportent que via leur bibliothèque de base. Mais, en général, même dans les langages qui les supportent, les valeurs multiples de retour ne sont pas souvent utilisées parce qu’elles sont imprécises :

    1. Les fonctions qui retournent des valeurs multiples sont difficiles à nommer clairement
    2. Il est aisé de se tromper dans l’ordre des valeurs retournées

      Code : Sélectionner tout
      (password, username) = GetUsernameAndPassword()
      (pour cette même raison, nombreux sont ceux qui évitent d’entrer trop de paramètres dans leur fonction, certains vont même jusqu’à dire qu’une fonction ne devrait pas avoir deux paramètres du même type)
    3. Les langages POO ont déjà une meilleure alternative aux valeurs de retour multiples : les classes. Elles sont plus fortement typées, elles maintiennent les valeurs de retour groupées comme une unité logique et elles gardent les noms / propriétés des valeurs retour suffisamment consistants.

      Le seul endroit où elles seraient assez pratiques se trouve être dans des langages (comme Python) où les valeurs de retour multiples d’une fonction peuvent être utilisées comme de multiples paramètres d’entrée pour l’autre. Mais, les cas d’utilisation où ces configurations sont plus adaptées que les classes sont assez restreints.
  • Parce que les fonctions sont des constructions mathématiques qui permettent d’effectuer un calcul et de retourner un résultat. En effet, bien des matériaux « sous le capot » de nombreux langages de programmation se concentrent uniquement sur une entrée et une sortie, avec les entrées multiples qui sont tout simplement une mince enveloppe autour de l’entrée. Cela n’a pas changé parce que les programmeurs ont découvert que les paramètres sont des constructions maladroites qui ne s’avèrent utiles que dans un ensemble de scénarios limités. Comme beaucoup d’autres choses, le support n’est pas présent parce que la demande / le besoin n’y est pas non plus.
  • En mathématiques, une fonction « bien définie » n’a qu’une seule sortie pour une entrée donnée (comme N.B, vous pouvez avoir des fonctions d’entrée unique et obtenir sémantiquement des entrées multiples en utilisant le currying)

    Pour des fonctions à valeurs multiples (par exemple la racine carrée d’un nombre entier positif), il suffit de retourner une collection ou une séquence de valeurs.

    Pour les types de fonctions dont vous parlez (les fonctions qui retournent différentes valeurs de différents types), je le perçois un peu différemment de ce que vous semblez voir : je vois la nécessité / le besoin de l’utilisation des paramètres de sortie comme solution de contournement pour un meilleur design ou une structure de données plus utile. Par exemple, j’aurais préféré que les méthodes *.TryParse(...) retournent une monade Maybe<T> au lieu d’utiliser un paramètre de sortie. Regardez un peu ce code dans F#:

    Code : Sélectionner tout
    1
    2
    3
    4
    let s = "1" 
    match tryParse s with 
    | Some(i) -> // do whatever with i 
    | None -> // failed to parse
    Le compilateur / l’IDE / le support d’analyse est très bon pour ces constructions. Ceci résoudrait la plupart des « besoins » de paramètres de sortie. Pour être complètement honnête, je n’arrive pas à imaginer d’autres méthodes où ce ne serait pas la solution.

    Pour les autres scénarios, ceux dont je ne me souviens pas, un simple tuple est suffisant.


Source : Stack Exchange

Et vous ?

Qu'en pensez-vous ?

Forum Langage de Programmation


Vous avez aimé cette actualité ? Alors partagez-la avec vos amis en cliquant sur les boutons ci-dessous :


 Poster une réponse

Avatar de heid heid - Membre confirmé https://www.developpez.com
le 14/09/2015 à 19:12
Réponse de uncle bob :
Si les x paramètre n'ont pas de cohésion c'est qu'il faut x fonctions, et si oui, et bien une classe représente bien la notion de cohésion entre variables

Réponse du dev sénior :
Parce que avec un seul paramètre de retour vous arrivez déjà à pondre du codé dégeu alors x j'imagine pas.
Avatar de Bono_BX Bono_BX - Membre confirmé https://www.developpez.com
le 14/09/2015 à 19:30
Réponse du dev sénior :
Parce que avec un seul paramètre de retour vous arrivez déjà à pondre du codé dégeu alors x j'imagine pas.



Merci pour ce grand moment de rire !
Avatar de Gugelhupf Gugelhupf - Modérateur https://www.developpez.com
le 14/09/2015 à 19:34
Je vois que l'exemple de Python est cité, le truc avec Python c'est qu'on ne précise pas les types des arguments. Dans un autre langage comme Java on pourrait se retrouver avec une signature de méthode comme (int, int, double) methode((int, int) param1, (double, String) param2) et à vrai je sais pas trop quoi penser, c'est moche et ça m'a l'air complexe à gérer.
De plus un passage par copie de référence (Java) ou référence (C++) suffit largement pour avoir une fonction qui modifie plusieurs variables.
Avatar de super_navide super_navide - Provisoirement toléré https://www.developpez.com
le 14/09/2015 à 19:39
C'est une bonne question pourquoi ??

exemple en java ca donnerai

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
int , int minEtMax(List<Integer> list) { 
int min = list.get(0); 
int max = list.get(0); 
for(Integer i:list) { 
if (i > max ){ 
max =i; 
} 
if (i < min) { 
min = i ; 
 } 
return min,max; 
}
ou

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
int , int maxEtIndex(List<Integer> l) { 
int idx =0; 
int max = list.get(0); 
for(int j=0;j < l.size() ;j++) { 
Integer val = l.get(j) 
if (val > max ){ 
max =val; 
idx =j 
} 
return max,idx; 
}
non c une bonne idée, évidement il y a plein d’intégriste du code qui vont trouvé une raison débile pour pas le faire
Avatar de super_navide super_navide - Provisoirement toléré https://www.developpez.com
le 14/09/2015 à 19:41
Citation Envoyé par Gugelhupf  Voir le message
Je vois que l'exemple de Python est cité, le truc avec Python c'est qu'on ne précise pas les types des arguments. Dans un autre langage comme Java on pourrait se retrouver avec une signature de méthode comme (int, int, double) methode((int, int) param1, (double, String) param2) et à vrai je sais pas trop quoi penser, c'est moche et ça m'a l'air complexe à gérer.
De plus un passage par copie de référence (Java) ou référence (C++) suffit largement pour avoir une fonction qui modifie plusieurs variables.

oui et créer en java des classes qui servent que pour une fonction , de plus créer un objet ça a un coût en java.
Avatar de super_navide super_navide - Provisoirement toléré https://www.developpez.com
le 14/09/2015 à 19:44
Citation Envoyé par Bono_BX  Voir le message


Merci pour ce grand moment de rire !

La notion de code degeux est relative , il faudrait faire une métrique pour le code degueux.
De toute façon le code est toujours dégueux et pas maintenable pour celui qui ne le comprend pas......
Avatar de codec_abc codec_abc - Membre actif https://www.developpez.com
le 14/09/2015 à 19:59
Pour commencer je trouve l'article un peu brouillon et d'ailleurs c'est qui le "vous" dans l'article ? Le lecteur ?

Ensuite, je suis en désaccord (plus ou moins fort) avec tous les arguments avancées :
Pour la première partie :
1. Je vois pas pourquoi les fonctions qui retournent plusieurs argument seraient nécessairement plus dures à nommer. C'est clair que si on utilise trop de "valeurs de retours" ça devient confus mais pas forcément plus que les fonctions/méthodes qui prennent un grand nombre d'arguments.
2. On peut aussi se tromper pour les paramètres. Exemple getPixel(int x, int y) vs getPixel(int y, int x). Le nommage permet de lever l’ambiguïté (à condition qu'il soit bon). Ça peut aussi être le cas pour les paramètres de retours.
3. L'argument n'a aucun sens. Je vois pas en quoi avoir plusieurs valeurs de retour d'une fonction ferait perdre l'information de typage pour chaque valeur.

La deuxième partie n'est pas clair. Je ne comprends pas ou l'auteur veut en venir.

Pour le point 3, ce n'est parce qu'on a de multiple valeur de retours qu'une fonction n'est pas bijective (ou injective). Chaque valeur de retour peut très bien ne servir qu'a représenter une dimension. Exemple (x,y) = swapValue(i,j).
Avatar de lankoande lankoande - Membre confirmé https://www.developpez.com
le 14/09/2015 à 20:13
A mon avis l'une des premières raisons c'est la simplicité. Et puis je pense qu'on a vraiment pas assez de mal pour contourner ce cas. Dans les langages structurales comme le C moi je retourne un tableau de pointeurs ou de structures selon le besoin et dans les langages OO je retourne des objets ou des tableaux d'objets.
Avatar de sevyc64 sevyc64 - Modérateur https://www.developpez.com
le 14/09/2015 à 20:57
La toute première raison est une raison historique. Les premières fonctions de l'histoire étaient simplement des fonctions, ou opérations mathématiques. hors les opérations mathématiques ne retournent bien souvent qu'un seul résultat, le résultat du calcul effectué.
C'est historique et, on le sait tous très bien, en informatique l'historique à la vie très dure, il ne se fait pas déboulonné facilement.

Citation Envoyé par Gugelhupf  Voir le message
De plus un passage par copie de référence (Java) ou référence (C++) suffit largement pour avoir une fonction qui modifie plusieurs variables.

Tu prend le problème, pardon la solution à l'envers. Ce n'est pas que ça suffit largement, c'est que ça a été la méthode la plus simple et la plus élégante de contourner le problème.
Et encore, un problème récent, parce qu'au départ, les paramètres de fonctions étaient passé par référence. La raison était la quantité limitée de ressource. On allait pas s'amuser à dupliquer une valeur en mémoire quand chaque octet, chaque bit même était compté au plus juste.
Ce n'est que lorsque les ressources, en mémoire et en puissance de calcul se sont faites un peu plus large que l'idée est venue de passer les paramètres par valeur pour les sécuriser.

Citation Envoyé par codec_abc  Voir le message
1. Je vois pas pourquoi les fonctions qui retournent plusieurs argument seraient nécessairement plus dures à nommer. C'est clair que si on utilise trop de "valeurs de retours" ça devient confus mais pas forcément plus que les fonctions/méthodes qui prennent un grand nombre d'arguments.

Je pense que tu n'as pas bien compris l'exemple.
Ce qui est appelé nommage concerne bien le sens premier, c'est à dire le nom de la fonction
- Une fonction qui retourne un nom d'utilisateur sera écrite username = GetUsername() .
- Une fonction qui retourne un nom d'utilisateur et son mot de passe sera écrite (username, password) = GetUsernameAndPassword() .
- Une fonction qui retourne un nom d'utilisateur, son mot de passe et un identifiant sera écrite (username, password, matricule)= GetUsernameAndPasswordAndMatricule().
- Une autre (username, password, matricule, age)= GetUsernameAndPasswordAndMatriculeAndAgeDuCapitaine().

Ca devient vite impossible

Mais il est vrai qu'avec la POO, le problème est résolu, puisque même si l'on ne retourne toujours qu'un seul résultat, c'est une classe que l'on retourne, donc un ensemble de données cohérentes.

Mais effectivement, ça aurait une grande utilité que personne n'a mentionné.
Une fonction, en réalité, a besoin de retourner 2 résultats, et pas un seul
- le résultat du calcul, certes
- mais aussi et surtout le résultat de l’exécution du calcul, s'il s'est bien effectué, avec ou sans erreur, etc.
Sur ce point, on a tous pris l'habitude de donner des valeurs particulières au résultat (du calcul) pour faire passer l'information sur l’exécution de ce même calcul. Parce qu'on a pas vraiment le choix, mais conceptuellement c'est quand même une belle aberration. Qui pourrait être résolue pas les fonctions multi-retour
Avatar de Lcf.vs Lcf.vs - Membre éprouvé https://www.developpez.com
le 14/09/2015 à 22:49
Je vous suggère de jeter un oeil au destructuring assignment
Offres d'emploi IT
Architecte sécurité des systèmes d'information embarqués H/F
Safran - Ile de France - 100 rue de Paris 91300 MASSY
Architecte technique des systèmes d'information H/F
Safran - Ile de France - Évry (91090)
Ingénieur analyste programmeur (H/F)
Safran - Auvergne - Montluçon (03100)

Voir plus d'offres Voir la carte des offres IT
Contacter le responsable de la rubrique Accueil