Dans quelle (s) langue (s) la valeur de retour est-elle définie en affectant le nom de la fonction?

Jan 18 2021

Dans cette question de débordement de pile, le code d'origine a commis l'erreur d'utiliser le nom de la fonction comme variable et lui a attribué la valeur de retour. Un commentateur a mentionné qu'il utilisait autrefois un langage dans lequel c'était ainsi que vous renvoyiez la valeur des fonctions. Le commentaire se lit comme suit: "Je sais que j'ai utilisé une fois une langue dans laquelle la valeur de retour d'une fonction devait être affectée au nom de la fonction. Il est si ancien et obsolète que je ne me souviens même pas de quelle langue il s'agissait."

Cela me semble également familier, mais je ne me souviens pas non plus de quelle langue il s'agissait.

Quelqu'un a-t-il une meilleure mémoire que nous et peut nous dire de quelle langue il s'agit?

Réponses

50 WillHartung Jan 18 2021 at 22:45

Pascal fait ça, je n'en connais pas d'autres. Je ne sais pas si la pratique va de l'avant avec d'autres langues Wirth.

50 OmarL Jan 18 2021 at 23:14

Les langages de la famille Visual Basic font exactement cela. Cela inclut VBScript, VBA, Visual Basic et les versions antérieures. Je crois que ceux-ci héritent de la «fonctionnalité» de QBASIC. Par example

Public Function AddTwo(something as Integer)
    AddTwo = something + 2
End Function
29 scruss Jan 18 2021 at 23:03

Fortran, c'est sûr:

      PROGRAM TRIANG 
      WRITE(UNIT=*,FMT=*)'Enter lengths of three sides:' 
      READ(UNIT=*,FMT=*) SIDEA, SIDEB, SIDEC 
      WRITE(UNIT=*,FMT=*)'Area is ', AREA3(SIDEA,SIDEB,SIDEC) 
      END 

      FUNCTION AREA3(A, B, C) 
*Computes the area of a triangle from lengths of sides 
      S = (A + B + C)/2.0 
      AREA3 = SQRT(S * (S-A) * (S-B) * (S-C)) 
      END

(extrait du Guide du programmeur professionnel de Clive G. Page sur Fortran77 ).

Il est également défini de cette manière dans la norme Fortran ANSI X 3.9 1966 Fortran 66 .

22 user3840170 Jan 18 2021 at 23:54

Les premiers langages que je puisse trouver sont FORTRAN II et ALGOL 58, tous deux publiés la même année 1958; bien que le FORTRAN original (1956) puisse également être inclus.

Pour FORTRAN, la première page du chapitre du manuel traitant des fonctions contient cet exemple (p. 27):

FUNCTION AVRG (ALIST, N)
DIMENSION ALIST (500)
SUM = ALIST (1)
DO 10 I=2, N
SUM = SUM + ALIST (I)
AVRG = SUM / FLOATF (N)
RETURN
END (2, 2, 2, 2, 2)

FORTRAN II comprend également une autre syntaxe de fonction (p. 10), la définition de fonction sur une seule ligne, héritée de son prédécesseur:

FIRSTF(X) = A*X + B

Il n'est pas difficile de voir en quoi la première syntaxe est une extension naturelle de la seconde, elle-même issue de l'usage mathématique.

ALGOL 58 , de la même manière que FORTRAN, définit les deux `` fonctions '' sur une seule ligne:

Une déclaration de fonction déclare qu'une expression donnée est une fonction de certaines de ses variables. Ainsi, la déclaration donne (pour certaines fonctions simples) la règle de calcul pour affecter des valeurs à la fonction (cf. fonctions ) chaque fois que cette fonction apparaît dans une expression.

Forme: Δ ~ I n (I, I, ~, I): = E où les I sont des identifiants et E est une expression qui, parmi ses constituants, peut contenir des variables simples nommées par des identifiants apparaissant entre parenthèses.

et des «procédures», équivalentes à une définition actuelle de la fonction (au moins dans les langages de programmation impératifs / procéduraux). La valeur de retour est indiquée comme suit (p. 19):

Pour chaque procédure de sortie unique I (P i ) répertoriée dans l'en-tête, une valeur doit être affectée dans la procédure par une instruction d'affectation «I: = E» où I est l'identifiant nommant cette procédure.

Ces syntaxes ont ensuite été reprises par certains dialectes de BASIC (sous la forme de DEF FNet plus tard FUNCTION) et le descendant d'ALGOL Pascal: dans les compilateurs Pascal de Borland, l'attribution du nom de la fonction était la seule syntaxe prise en charge avant l'introduction de la Resultvariable dans Delphi 1.0.

C'est probablement Pascal que le commentateur mentionné s'est souvenu; certaines universités y enseignent encore la programmation et s'en tiennent généralement à la variété standard d'origine, au lieu des dialectes étendus modernes comme Object Pascal. (Cela ne fait pas vraiment partie de la question, mais je suppose que l'incompréhension du demandeur StackOverflow vient également de cela.)

17 Raffzahn Jan 19 2021 at 00:28

TL; DR:

Je dirais que c'est probablement PASCAL dont vous vous souvenez, car il était plutôt populaire au début des années 80, utilisé dans les cours universitaires tout au long des années 80 jusqu'aux années 90 et avait encore une certaine fraternité là-bas, notamment Delphi.


Un peu d'histoire

L'idée de base est que le nom de la fonction n'est pas seulement déjà réservé, donc pas besoin de proposer quoi que ce soit de différent, et son utilisation est une déclaration claire que c'est le résultat. Cela simplifie également la conception du compilateur, car un élément de données dédié peut être alloué dans la convention d'appel.

Il existe essentiellement deux lignes de patrimoine, FORTRAN et ALGOL.

Pour les deux certains de leurs descendants l'ont gardé, comme

  • quelques variantes BASIC de FORTRAN et
  • Pascal et Modula d'ALGOL.

D'autres l'ont laissé tomber, comme le suivi d'ALGOL

  • BCPL, qui a introduit la return()syntaxe,

ce qui est assez courant aujourd'hui car C l'a pris de BCPL.

Les idées de langage sont comme des gènes sautant entre les hôtes. Par exemple ADA, à bien des égards un petit-enfant ALGOL / PASCAL, s'est également tourné vers l'utilisation d'un returnélément.

Granddaddy FORTRAN a, au fil des ans, modifié la façon dont il renvoie les résultats des fonctions.

  • À l'origine, le résultat d'une fonction était affecté à l'identifiant de la fonction
  • avec FORTRAN 90, la définition explicite d'un nom de retour dans la tête de fonction a été introduite.

Bien qu'il ne s'agisse essentiellement que de sucre syntaxique, il présente un changement de style. Le raisonnement appliqué était qu'avec des constructions de récursion comme cela Foo = Foo(x-1)aurait l'air étrange. Mais je suppose que cela dépend de l'interprétation.

Il est intéressant ici aussi que FORTRAN II de 1958 a introduit une RETURNinstruction dans son effort pour ajouter de la programmation procédurale, mais son utilisation était simplement de renvoyer l'exécution à un appelant, la valeur de retour devant être définie séparément.

12 alephzero Jan 18 2021 at 23:02

Fortran a utilisé cette syntaxe, depuis la version la plus ancienne qui avait des fonctions jusqu'à Fortran 2008 et au-delà.

Cependant, Fortran 2008 a une option (encore plus déroutante?) Où vous pouvez déclarer un nom de variable différent qui est utilisé pour renvoyer une valeur de fonction! Par example

function xyz(argument) result(answer)
...
answer = 42
...
end function xyz

au lieu du style ancien

...
xyz = 42
...
9 another-dave Jan 19 2021 at 01:02

Algol 60 pour un.

Voici les mots pertinents du rapport révisé sur le langage algorithmique Algol 60 .

5.4.4. Valeurs des désignateurs de fonction.

Pour qu'une déclaration de procédure définisse la valeur d'un désignateur de fonction, il doit y avoir, dans le corps de déclaration de procédure, une ou plusieurs instructions d'affectation explicites avec l'identificateur de procédure dans une partie gauche; au moins l'un d'entre eux doit être exécuté et le type associé à l'identificateur de procédure doit être déclaré par l'apparition d'un déclarateur de type comme tout premier symbole de la déclaration de procédure. La dernière valeur ainsi attribuée est utilisée pour continuer l'évaluation de l'expression dans laquelle l'indicateur de fonction apparaît.

Toute occurrence de l'identificateur de procédure dans le corps de la procédure autre que dans une partie gauche d'une instruction d'affectation indique l'activation de la procédure.

La dernière phrase est significative - elle montre que le nom du type procédure (fonction) n'est pas traité «comme» une variable dans le corps de la procédure (fonction); au contraire, c'est uniquement une affectation qui a une casse spéciale.

Dans Algol 60, un appel à une fonction qui ne prend aucun argument n'est pas suivi de parenthèses vides: donc n := readplutôt que n := read().

La dernière phrase est également connue comme étant la phrase qui a introduit des procédures récursives dans la langue. Mais ce n'est pas pertinent pour cette réponse.

6 StephenKitt Jan 18 2021 at 23:03

BASIC est un autre langage avec des fonctions où certains dialectes utilisaient l'affectation du nom de la fonction pour fournir la valeur de retour. Les premiers dialectes étaient similaires aux fonctions à ligne unique Fortran:

DEF FND(x) = x*x

Mais les dialectes ultérieurs ont permis des variantes plus complexes, similaires aux fonctions multilignes Fortran :

DEF FNPeekWord& (A&)
  FNPeekWord& = PEEK(A&) + 256& * PEEK(A& + 1)
END DEF
5 LyndonWhite Jan 19 2021 at 20:38

MATLAB / Octave fait également cela.

C'est de 1984; donc pas aussi vieux que certains des autres.

Il imitait probablement Fortran, car il était initialement conçu comme un outil de haut niveau. En plus des bibliothèques Fortran comme Linpack et Eispack.

5 chasly-supportsMonica Jan 19 2021 at 21:29

Je crois que SNOBOL4 a fait cela. http://berstis.com/greenbook.pdf

Voici un exemple de définition et d'utilisation d'une fonction pour calculer des factorielles de nombres:

   DEFINE('FACT(N)') :(SKIPFCN)
 * Set value to 1
 FACT      FACT = 1
 * Return 1 if N<2
 * Return N*((N-1)!) with recursive call
   FACT = GT(N,1) FACT(N - 1) * N :(RETURN)
 SKIPFCN
   OUTPUT = '5 factorial is ' FACT(5)

http://berstis.com/s4ref/prim3e.htm

4 d3jones Jan 19 2021 at 07:12

Verilog (1995/2001) renvoie également par affectation à une variable implicite. SystemVerilog a ajouté l'instruction "return" mais l'affectation classique est toujours disponible.

1 arne Jan 21 2021 at 03:02

Haskell (à partir de 1990) le fait également:

doubleMe x = x + x  

définit une fonction doubleMed'un paramètre xet lui assigne le corps x+xde la fonction , voir le grand Learn You A Haskell For Great Good

mathrick Jan 19 2021 at 13:08

Pascal est celui que j'ai personnellement utilisé pour le faire. Common Lisp un peu, mais pas vraiment, en ce sens que les valeurs de retour sont presque toujours implicites (c'est-à-dire que chaque instruction a une valeur et que la dernière valeur d'un bloc est la valeur de retour du bloc), donc vous voyez très rarement une déclaration de retour explicite, mais quand vous avez besoin de retourner une valeur et ne peut pas utiliser la manière implicite, la façon de le faire est en utilisant le RETURN-FROM[*] déclaration, comme suit: (return-from function-name value).

[*] Il y a aussi une RETURNinstruction, mais c'est un raccourci pour (return-from nil value), et n'aura pas pour effet de rendre VALUEla valeur de la fonction dans laquelle elle a été exécutée. C'est un grand écueil pour les débutants venant de C et de ses descendants.