Quali linguaggi di programmazione imperativi non supportano la ricorsione?


21

Per quanto ne so, tutti i moderni linguaggi di programmazione imperativa supportano la ricorsione nel senso che una procedura può chiamare se stessa. Questo non è sempre stato il caso, ma non riesco a trovare fatti concreti con una rapida ricerca su Google. Quindi la mia domanda è:

Quali lingue non hanno supportato la ricorsione sin dall'inizio e quando è stato aggiunto tale supporto?

Risposte:


21

Non sono sicuro che COBOL lo faccia (certamente non lo è stato in una sola volta), ma non riesco nemmeno a immaginare che a nessuno importi molto.

Fortran ha da allora Fortran 90, ma richiede l'utilizzo della recursiveparola chiave per indicare che una subroutine è ricorsiva.

PL / I era praticamente lo stesso - la ricorsione era supportata, ma dovevi dirlo esplicitamente quali procedure erano ricorsive.

Dubito che ce ne siano molti di più però. Quando si arriva a questo, proibire la ricorsione era principalmente qualcosa che IBM faceva nei loro progetti linguistici, per la semplice ragione che i mainframe IBM (360/370/3090 / ...) non supportano uno stack nell'hardware. Quando la maggior parte delle lingue proveniva da IBM, proibivano principalmente la ricorsione. Ora che provengono tutti da altri posti, la ricorsione è sempre consentita (anche se dovrei aggiungere che alcune altre macchine, in particolare l'originale Cray 1, non avevano neanche il supporto hardware per uno stack).


I computer Control Data del periodo non supportavano nemmeno la ricorsione (le chiamate della subroutine venivano eseguite con un'istruzione che modificava il codice per inserire un salto nell'istruzione di chiamata + 1). Quando Wirth sviluppò Pascal sul 6600, presumibilmente dovette escogitare un nuovo modo di chiamare subroutine.
David Thornley,

@ David: sì - e non a caso, sono stati progettati anche da Seymour Cray. Una volta ho avuto modo di guardare il compilatore Pascal 6000, ma non ricordo di aver visto cosa ha fatto per generare (simulare?) Stack frame.
Jerry Coffin,

notably the original cray 1Quindi, non hai bisogno di ricorsione per clonare i dinosauri? Immagino che spetti a noi scimmie oscillare tra gli alberi.
normanthesquid,

2
anche CAML (e OCAML, F #) necessitano di funzioni ricorsive contrassegnate esplicitamente.
jk.

1
@Panzercrisis: non sono sicuro che IBM sia stata coinvolta nell'x86, ma i loro attuali mainframe risalgono direttamente all'IBM 360, che è arrivato sul mercato nel 1964, quindi il design di base precede l'x86 di un paio di decenni circa.
Jerry Coffin,

16

Wikipedia dice:

Le prime lingue come Fortran inizialmente non supportavano la ricorsione perché le variabili erano allocate staticamente, così come la posizione per l'indirizzo di ritorno.

http://en.wikipedia.org/wiki/Subroutine#Local_variables.2C_recursion_and_re-entrancy

FORTRAN 77 non consente la ricorsione, lo fa Fortran 90 (le routine ricorsive devono essere esplicitamente dichiarate così).

La maggior parte dei compilatori FORTRAN 77 consente la ricorsione, alcuni (ad es. DEC) richiedono l'utilizzo di un'opzione di compilazione (vedere il capitolo Opzioni di compilazione). GNU g77, che è strettamente conforme allo standard Fortran 77, non consente affatto la ricorsione.

http://www.ibiblio.org/pub/languages/fortran/ch1-12.html


tra l'altro c'era almeno un compilatore FORTRAN 77 che, sebbene supportasse tecnicamente la ricorsione, il numero totale di frame di stack che si potevano avere erano così piccole che la ricorsione non era effettivamente utilizzabile per molti problemi
jk.

6

Il linguaggio di programmazione OpenCL non supporta la ricorsione. (vedere la sezione 6.8 delle specifiche OpenCL )

L'attuale motivazione per questo è a) una mancanza di spazio per stack profondi b) il desiderio di conoscere, staticamente, le allocazioni totali necessarie al fine di ottimizzare le prestazioni in presenza di grandi set di registri e di un ampio allineamento.

Questo potrebbe applicarsi anche ad altri linguaggi di programmazione GPU, ad esempio linguaggi shader.


2

Alcuni compilatori c per piccoli microcontrollori non supportano la ricorsione, presumibilmente perché hanno dimensioni dello stack estremamente limitate.


Alcuni di questi microcontrollori (ad esempio la famiglia PIC16) hanno solo uno stack di chiamate hardware (non accessibile dalle istruzioni) e non hanno altre forme di stack, quindi le funzioni non possono avere variabili locali quando si utilizza la ricorsione (poiché è chiaramente necessario uno stack di dati per quello ...) Riferimento: en.wikipedia.org/wiki/PIC_microcontroller#Stacks
Ale

1

BASIC, ai tempi dei numeri di riga, tendeva ad avere scarso supporto alla ricorsione. Molti (tutti?) BASIC di quel tempo supportavano le chiamate nidificate di gosub, ma non supportavano un modo semplice per passare parametri o restituire valori in un modo che rendesse utile l'auto-chiamata.

Molti dei primi computer avevano problemi con la ricorsione, perché usavano istruzioni di chiamata che scrivevano l'indirizzo di ritorno all'inizio della routine chiamata (PDP8, la famiglia di macchine IAS, probabilmente più architetture con cui non ho familiarità), di solito in modo tale che era il codice macchina per "Vai all'istruzione dopo quello che chiamava la routine".


1

Dipende da cosa intendi per " supporto ". Per supportare la ricorsione è necessario uno stack in cui ri-istanziare le variabili locali ad ogni rientro.

Anche se il linguaggio non ha il concetto di variabili locali, se ha il concetto di "subroutine" e ha un modo per gestire l'indicizzazione tra variabili identiche (aka array) è possibile incrementare / decrementare un indice globale ad ogni entrata / uscita di una funzione e accedervi attraverso un membro di uno o più array.

Non so se questo può essere chiamato "supporto". I fatti sono che ho scritto funzioni ricorsive con ZX-Spectrum BASIC, come ho fatto in Fortran77 come in COBOL ... sempre con quel trucco.


1

Il linguaggio assembly non supporta direttamente la ricorsione - devi "farlo da solo", in genere spingendo i parametri sullo stack della macchina.


2
Supporta la ricorsione in quanto supporta le chiamate di metodo. Di solito c'è CALLun'istruzione, che spinge automaticamente l'IP nello stack prima di passare alla subroutine e RETun'istruzione che inserisce l'indirizzo di ritorno nell'IP. Non c'è motivo per cui non sia possibile CALLil proprio punto di ingresso.
Blorgbeard

@Blorgbeard - assolutamente vero, anche se direi che questo non è sufficiente per essere considerato "supporta la ricorsione" nel senso comunemente inteso in quanto non gestisce i parametri necessari per la chiamata ricorsiva.
Mikera,

1
Bene, le chiamate ricorsive non hanno tecnicamente bisogno di parametri, giusto? void f() { f(); }è ricorsivo.
Blorgbeard

Tecnicamente no. Ma essere in grado di codificare un caso banale non significa che IMHO dovrebbe descrivere l'assemblaggio come "supporto della ricorsione". Gli usi più pratici della ricorsione richiedono parametri.
Mikera,

Suppongo che potresti dirlo. Ma in tal caso, anche il montaggio non supporta i loop (è necessario manualmente CMP e JNZ). Immagino sia una questione di ciò che chiami "supporto".
Blorgbeard
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.