È possibile avere funzioni annidate, senza avere chiusure, in un linguaggio con lessical scope che ha funzioni di prima classe?

2

A closure is a record storing a function, together with an environment: A mapping associating each free variable of the function (variables that are used locally, but defined in an enclosing scope) with the value or reference to which the name was bound when the closure was created. (Wikipedia)

Ecco quello che capisco. Una funzione può accedere a 3 tipi di variabili (assumiamo JavaScript):

  1. Parametri: i parametri di una funzione.
  2. Variabili locali: le variabili definite all'interno di una funzione. (ma non le variabili definite in una funzione nidificata. Cioè, una funzione non può accedere a variabili definite in un'altra funzione, dove questa altra funzione è definita all'interno della funzione di cui stiamo parlando)
  3. Variabili libere: le variabili definite al di fuori della funzione. Cioè, la funzione può accedere alle variabili definite nella funzione che circonda la nostra funzione, e le variabili definite nella funzione che circonda la funzione che circonda la nostra funzione, ecc.

Di questi 3 tipi, i valori delle variabili di tipo 1 e 2 sono ben noti al momento della chiamata di una funzione. Tuttavia, le variabili di tipo 3 possono avere qualsiasi valore nel momento in cui viene chiamata una funzione. Per quanto ne so, questa è una proprietà delle lingue con scope dinamiche. Cioè, AFAIK, nelle lingue con lessical scope, non possiamo avere una situazione del genere.

Ecco dove una chiusura entra in scena. Una chiusura lega le variabili libere di una funzione. Quindi, non esiste alcuna variabile che non abbia un valore ben noto, al momento in cui viene chiamata una funzione.

Quindi, la mia domanda è la seguente:

Are closures a must have in lexically scoped languages, which allow nested functions and which have first class functions?

Per me, sembra così. Perché se le funzioni di prima classe annidate sono consentite in una lingua senza avere chiusure, significa che le variabili libere avranno valori non deterministici nel momento in cui viene chiamata una funzione. Ma AFAIK, con valori non deterministici è una proprietà delle lingue con ambito dinamico . Quindi, sostengo:

If a language claims to be lexically scoped, and if a language allows nested first class functions, then, by definition, every function in that language is (must be) a closure.

Sono corretto in questo?

    
posta Utku 11.12.2016 - 11:25
fonte

1 risposta

2

Non credo che la tua conclusione sia vera.

function outer1() {
  const foo = 42;

  function inner1() {};
}

In questo caso, inner1 non è una chiusura, ma è una funzione annidata. Semplicemente non usa alcun identificatore dall'ambito circostante.

function outer2() {
  const foo = 42;

  function inner2() { return foo; };

  return inner2();
}

Qui, inner2 fa usa foo , ma inner2 non lascia mai l'ambito di outer2 , e quindi non "chiude" il suo ambiente circostante. Non è una chiusura.

function outer3() {
  const foo = 42;

  function inner3() { return 23; };

  return inner3;
}

Qui, inner3 fa lascia l'ambito di outer3 , ma non usa alcuna variabile libera. Di nuovo, non una chiusura.

function outer4() {
  const foo = 42;

  function inner4() { return foo; };

  return inner4;
}

Solo inner4 è in realtà una chiusura: lascia l'ambito di outer4 e si chiude sul suo ambiente e "lo porta con sé".

Quindi, come puoi vedere, è perfettamente possibile avere funzioni annidate che non sono chiusure in un linguaggio con lessicalismo, purché almeno una delle seguenti condizioni sia vera:

  1. la funzione nidificata non ha accesso all'ambiente circostante
  2. la funzione annidata non lascia l'ambito dell'ambiente circostante

Per essere onesti, non riesco a pensare ad un linguaggio che abbia queste restrizioni, però. Ma ci sono sono restrizioni simili sulle variabili catturate dal ref-in in lambda C ++, penso. Un lambda C ++ che cattura una variabile per riferimento non può usare quella variabile o non lasciare l'ambito. Se fa entrambe le cose, il risultato è un comportamento indefinito (e molto probabilmente causerà un accesso illegale alla memoria).

    
risposta data 11.12.2016 - 12:47
fonte

Leggi altre domande sui tag