2013-10-27 14 views
5

Sono in un grande dilemma, prendere il seguente codice scritto in ML:scope lessicale in Python vs ML

val x = 1 
fun f(y) = x + y 
val x = 2 
val y = 3 
val z = f (x + y) 

Il valore di z è 6. Ora, se io scrivere lo stesso codice in Python il valore di z sarebbe 7. E entrambe le lingue sostengono (in effetti gli insegnanti che insegnano queste lingue affermano questo) di avere uno scopo lessico/statico. Ma sembra che solo ML lo abbia usando l'ambiente che si stava creando quando la funzione f è stata definita ogni volta che f è chiamato

Qualsiasi suggerimento sarebbe molto apprezzato!

Grazie!

risposta

6

In Python, le chiusure sono variabili, non in base al valore. Pertanto, quando si fa riferimento a x in una funzione, fa riferimento al valore più recente assegnato a x, non al valore di x quando la funzione è stata definita. Questo ottiene risultati non intuitivi come quello qui sotto:

adders = [] 
for x in range(10): 
    adders.append(lambda y: x+y) 

avete intenzione di fare un elenco di funzioni che aggiungono x ad un valore, dove x varia da 0 ... 9, ma invece hanno tutti aggiungere 9 perché questo è il valore di x alla fine del ciclo.

È possibile eseguire l'override utilizzando un argomento predefinito per associare il nome al relativo valore al momento della definizione della funzione.

x = 1 
f = lambda y, x=x: x + y # x inside f is now locked at 1 
x = 2 
y = 3 
z = f(x + y) 

In questo esempio non sei nemmeno in realtà si tratta di una chiusura: x qui è in realtà una variabile globale. In Python, una chiusura può essere creata solo quando una funzione è definita all'interno di un'altra funzione e lo spazio dei nomi principale o globale non è una funzione. Ma vale lo stesso principio: la variabile globale può ovviamente essere cambiata dopo che la funzione è stata definita, quindi se si desidera "bloccare" il suo valore al momento della definizione della funzione, si utilizza un argomento predefinito.

+0

Bene, si potrebbe anche dire che in ML, le variabili sono anche catturate per riferimento - le variabili non possono essere assegnate in ML, quindi se le variabili sono catturate dal valore o dal riferimento non fa differenza. – newacct

+0

Sì, non ne so abbastanza di ML per dire qualcosa al riguardo. :-) – kindall

6

In ML - almeno, nella parte funzionale di ML - non esiste l'assegnazione di variabili. Dopo aver dichiarato che val x = 1, non è possibile modificare il valore di tale x.

Che cosa è può do, tuttavia, è dichiarare un altro x. Quando dici val x = 2, stai introducendo una nuova variabile chiamata x, che in pratica nasconde semplicemente quella vecchia. Ma la funzione f è già stata definita per fare riferimento all'originale x, quindi non è interessata.

ML supporta mutable types, che può essere riassegnato proprio come le variabili in Python. Ma si allontanano così tanto dal paradigma funzionale che raramente dovresti avere qualche ragione per usarli. Se vuoi programmare in questo modo, Python è un linguaggio molto migliore per questo.

+1

Non ci sono assegnazioni variabili in ML, periodo. (Semplicemente non esiste nemmeno una sintassi per l'assegnazione a una variabile.) È possibile avere riferimenti a strutture di dati mutabili ed è possibile modificare tale struttura di dati. Ma non puoi assegnare a una variabile. – newacct