In quale lingua è impostato il valore di ritorno assegnando al nome della funzione?

Jan 18 2021

In questa domanda di Stack Overflow il codice originale ha commesso l'errore di utilizzare il nome della funzione come variabile e le ha assegnato il valore di ritorno. Un commentatore ha detto di aver usato una volta un linguaggio in cui questo era il modo in cui restituivi il valore dalle funzioni. Il commento dice "So che una volta ho usato una lingua in cui il valore di ritorno di una funzione doveva essere assegnato al nome della funzione. È così antico e obsoleto che non riesco nemmeno a ricordare quale lingua fosse".

Anche questo suona familiare a me, ma non ricordo nemmeno che lingua fosse.

Qualcuno ha una memoria migliore di noi e può dirci di che lingua è?

Risposte

50 WillHartung Jan 18 2021 at 22:45

Pascal fa questo, non ne conosco altri. Non so se la pratica va avanti con altre lingue Wirth.

50 OmarL Jan 18 2021 at 23:14

Le lingue della famiglia Visual Basic fanno esattamente questo. Ciò include VBScript, VBA, Visual Basic e versioni precedenti. Credo che questi ereditino la "caratteristica" di QBASIC. Per esempio

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

Fortran, di sicuro:

      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

(dalla Guida per programmatori professionisti di Clive G. Page a Fortran77 ).

È anche definito in questo modo nello standard Fortran ANSI X 3.9 1966 Fortran 66 .

22 user3840170 Jan 18 2021 at 23:54

Le prime lingue di questo tipo che riesco a trovare sono FORTRAN II e ALGOL 58, entrambi pubblicati nello stesso anno 1958; sebbene l'originale FORTRAN (1956) possa senza dubbio essere incluso.

Per FORTRAN, la prima pagina del capitolo del manuale che copre le funzioni contiene questo esempio (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 include anche un'altra sintassi di funzione (p. 10), la definizione di funzione a riga singola, ereditata dal suo predecessore:

FIRSTF(X) = A*X + B

Non è difficile vedere come la prima sintassi sia una naturale estensione della seconda, a sua volta derivante dall'uso matematico.

ALGOL 58 , analogamente a FORTRAN, definisce entrambe le 'funzioni' a riga singola:

Una dichiarazione di funzione dichiara che una data espressione è una funzione di alcune delle sue variabili. In tal modo, la dichiarazione fornisce (per alcune funzioni semplici) la regola di calcolo per assegnare valori alla funzione (cfr. Funzioni ) ogni volta che questa funzione appare in un'espressione.

Forma: Δ ~ I n (I, I, ~, I): = E dove gli io sono identificatori ed E è un'espressione che, tra i suoi costituenti, può contenere semplici variabili nominate da identificatori che compaiono tra parentesi.

e "procedure", equivalenti a una definizione di funzione odierna (almeno nei linguaggi di programmazione imperativi / procedurali). Il valore restituito è indicato come segue (p. 19):

Per ogni singola procedura di output I (P i ) elencata nell'intestazione, deve essere assegnato un valore all'interno della procedura mediante un'istruzione di assegnazione “I: = E” dove I è l'identificativo che denomina tale procedura.

Queste sintassi furono successivamente riprese da alcuni dialetti del BASIC (sotto forma di DEF FNe successivi FUNCTION) e del discendente Pascal di ALGOL: nei compilatori Pascal di Borland, l'assegnazione al nome della funzione era l'unica sintassi supportata prima dell'introduzione della Resultvariabile in Delphi 1.0.

È probabilmente Pascal quello che il commentatore menzionato ha ricordato; alcune università insegnano ancora la programmazione al suo interno e di solito si attengono alla varietà standard originale, invece dei dialetti estesi moderni come Object Pascal. (Questo non fa davvero parte della domanda, ma presumo che l'incomprensione del richiedente StackOverflow derivi anche da questo.)

17 Raffzahn Jan 19 2021 at 00:28

TL; DR:

Direi, molto probabilmente è PASCAL che ricordi, dato che era piuttosto popolare nei primi anni '80, usato nei corsi universitari dagli anni '80 fino agli anni '90 e aveva ancora qualche amicizia lì dopo, in particolare Delphi.


Un po 'di storia

L'idea di base è che il nome della funzione non solo è già riservato, quindi non è necessario inventare qualcosa di diverso, e usarlo è una chiara affermazione che questo è il risultato. Inoltre semplifica la progettazione del compilatore, poiché un elemento di dati dedicato può essere allocato all'interno della convenzione di chiamata.

Esistono essenzialmente due linee di eredità, FORTRAN e ALGOL.

Per entrambi alcuni dei loro discendenti lo tenevano, tipo

  • alcune varianti BASIC da FORTRAN e
  • Pascal e Modula di ALGOL.

Altri lo hanno lasciato cadere, come il seguito di ALGOL

  • BCPL, che ha introdotto la return()sintassi,

che è abbastanza comune oggi poiché C lo ha preso da BCPL.

Le idee linguistiche sono come i geni che saltano tra gli ospiti. Ad esempio ADA, per molti versi un nipote di ALGOL / PASCAL, si è rivolto anche lui all'utilizzo di un returnelemento.

Granddaddy FORTRAN, nel corso degli anni, ha modificato il modo in cui restituisce i risultati delle funzioni.

  • Originariamente il risultato di una funzione era assegnato all'identificatore della funzione
  • con FORTRAN 90 è stata introdotta la definizione esplicita di un nome di ritorno nell'intestazione della funzione.

Sebbene questo sia essenzialmente solo zucchero sintattico, presenta un cambiamento di stile. Il ragionamento applicato era che con costruzioni di ricorsione il simile Foo = Foo(x-1)sarebbe apparso strano. Ma immagino che dipenda dall'interpretazione.

È interessante notare che anche qui FORTRAN II del 1958 ha introdotto RETURNun'istruzione nel suo tentativo di aggiungere la programmazione procedurale, ma il suo utilizzo era semplicemente quello di restituire l'esecuzione a un chiamante, il valore restituito doveva essere impostato separatamente.

12 alephzero Jan 18 2021 at 23:02

Fortran ha utilizzato questa sintassi, dalla prima versione che aveva tutte le funzioni fino a Fortran 2008 e oltre.

Tuttavia Fortran 2008 ha un'opzione (ancora più confusa?) In cui è possibile dichiarare un nome di variabile diverso che viene utilizzato per restituire un valore di funzione! Per esempio

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

invece del vecchio stile

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

Algol 60 per uno.

Ecco le parole rilevanti dal Rapporto Rivisto sul Linguaggio Algoritmico Algol 60 .

5.4.4. Valori dei designatori di funzione.

Affinché una dichiarazione di procedura definisca il valore di un designatore di funzione, devono essere presenti, all'interno del corpo della dichiarazione di procedura, una o più istruzioni di assegnazione esplicita con l'identificatore di procedura nella parte sinistra; almeno uno di questi deve essere eseguito e il tipo associato all'identificatore di procedura deve essere dichiarato attraverso la comparsa di un dichiaratore di tipo come primo simbolo della dichiarazione di procedura. L'ultimo valore così assegnato viene utilizzato per continuare la valutazione dell'espressione in cui ricorre il designatore di funzione.

Qualsiasi occorrenza dell'identificativo della procedura all'interno del corpo della procedura diversa dalla parte sinistra di un'istruzione di assegnazione denota l'attivazione della procedura.

L'ultima frase è significativa: mostra che il nome del tipo procedura (funzione) non è trattato "proprio come" una variabile all'interno del corpo della procedura (funzione); piuttosto, è solo un incarico che è un caso speciale.

In Algol 60, una chiamata a una funzione che non accetta argomenti non è seguita da parentesi vuote: quindi n := readpiuttosto che n := read().

L'ultima frase è anche famosa come la frase che ha ottenuto procedure ricorsive nella lingua. Ma questo non è pertinente a questa risposta.

6 StephenKitt Jan 18 2021 at 23:03

BASIC è un altro linguaggio con funzioni in cui alcuni dialetti usavano l'assegnazione al nome della funzione per fornire il valore di ritorno. I primi dialetti erano simili alle funzioni a riga singola di Fortran:

DEF FND(x) = x*x

Ma i dialetti successivi consentirono varianti più complesse, simili alle funzioni multilinea di Fortran :

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

Anche MATLAB / Octave fa questo.

È del 1984; quindi non vecchio come alcuni degli altri.

Probabilmente stava imitando Fortran, poiché era originariamente concepito come uno strumento di alto livello. Oltre alle librerie Fortran come Linpack ed Eispack.

5 chasly-supportsMonica Jan 19 2021 at 21:29

Credo che SNOBOL4 abbia fatto questo. http://berstis.com/greenbook.pdf

Quello che segue è un esempio della definizione e dell'uso di una funzione per calcolare fattoriali di numeri:

   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) restituisce anche per assegnazione alla variabile implicita. SystemVerilog ha aggiunto l'istruzione "return" ma l'assegnazione classica è ancora disponibile.

1 arne Jan 21 2021 at 03:02

Anche Haskell (dal 1990) fa questo:

doubleMe x = x + x  

definisce una funzione doubleMedi un parametro xe gli assegna il corpo della funzione x+x, vedere il grande Learn You A Haskell For Great Good

mathrick Jan 19 2021 at 13:08

Pascal è uno che ho usato personalmente per farlo. Common Lisp un po '-sorta-ma-non-lo fa davvero, in quanto i valori di ritorno sono quasi sempre impliciti (cioè ogni istruzione ha un valore e l'ultimo valore in un blocco è il valore di ritorno del blocco), quindi molto raramente vedi una dichiarazione di ritorno esplicito, ma quando è necessario restituire un valore e non è possibile utilizzare il modo implicito, il modo per farlo è quello di utilizzare il RETURN-FROM[*] dichiarazione, in questo modo: (return-from function-name value).

[*] C'è anche RETURNun'istruzione, ma è un'abbreviazione per (return-from nil value)e non avrà l'effetto di rendere VALUEil valore della funzione in cui è stata eseguita. È una grande trappola per i neofiti provenienti da C e dai suoi discendenti.