2010-08-15 6 views
12

Come annullare la definizione di una variabile in Scheme? È possibile?Come annullare la definizione di una variabile in Scheme?

+0

Puoi dirci perché ne hai bisogno o qual è la tua intenzione? – mathk

+0

Sono novizio su Schema o linguaggio funzionale. Ho immaginato l'ambiente come un hash-table e mi sono preoccupato di un qualche tipo di gestione della memoria. Pensavo che l'esplicita un-definging richiedesse di rilasciare la memoria sotto GC. E ora sono un po 'confuso. Sto cercando di capire il comportamento di livello inferiore di Scheme. – Eonil

+0

Naturalmente, lo schema di rilascio della memoria non è obbligatorio su Scheme, ma voglio sapere i dettagli. – Eonil

risposta

5

In Schema, le variabili sono definite con lambda o con una delle varie opzioni. Se vuoi che uno di essi sia "indefinito", tutto ciò che devi fare è lasciare l'ambito in cui si trovano. Ovviamente, non li sta davvero indebolendo, è solo che la variabile non è più legata alla sua definizione precedente.

Se si stanno creando definizioni di livello superiore, utilizzando (define), tecnicamente si sta definendo una funzione. Poiché Scheme è funzionale, le funzioni non scompaiono mai veramente. Suppongo che tecnicamente, sia memorizzato in qualche tipo di funzione dell'ambiente da qualche parte, quindi se tu fossi intimamente familiare con la tua implementazione (e non sia salvaguardato in qualche modo) potresti probabilmente sovrascriverlo con la tua definizione dell'ambiente globabl. Escludendo, direi che la soluzione migliore sarebbe ridefinire la funzione per restituire l'elenco nullo, che è davvero vuoto come si ottiene.

+1

si potrebbe anche fare (set! X (display 'ignorato)) perché 'display' restituisce" un valore non specificato ". –

+1

È possibile definire valori non funzionali al livello superiore in Schema e le funzioni associate localmente effettivamente "vanno via". – Anthony

+0

Grazie per la risposta. Mi sono reso conto che la mia domanda era qualcosa di sbagliato :) Mi sono reso conto che definire definisce qualcosa nell'ambito di alto livello, quindi è rimasto fino alla fine dello scopo (uscita programma) – Eonil

1

Non è possibile disassociare una variabile in Schema standard. Potresti impostare! la variabile a 'indefinito, credo, o potresti scrivere un metainterpreter che reifica gli ambienti, permettendoti di introdurre la tua nozione di variabili indefinibili.

2
(set! no-longer-needed #f) 

Questo raggiunge l'effetto desiderato? Puoi anche usare define al livello più alto.

guile> (define nigel "lead guitar") 
guile> nigel 
"lead guitar" 
guile> (define nigel #f) 
guile> nigel 
#f 
guile> 

È quindi possibile ri-define la variabile. Tutto dipende ovviamente dalla portata delle variabili: vedi Greg's answer.

+0

Solo una nota per Eonil: set! distrugge la trasparenza referenziale perché introduce effetti collaterali, e quindi dovrebbe essere evitato se si vuole rimanere puramente funzionali. – Greg

+0

Impostando una variabile su false non è come definirla. – ceving

1

Penso che se il tuo punto è fare l'equivalente di "libero" o de-allocare, allora non sei praticamente sfortunato. non puoi de-allocare una variabile. Si CAN ridefinirlo a qualcosa di piccolo, come #f, ma una volta terminato (definire foo 'bar) la variabile foo esisterà in qualche modo fino alla fine del programma.

D'altra parte, se si utilizza lasciare, o letrec, ovviamente, il nome esiste solo fino a quando le pertinenti parentesi vicino ...

+0

Grazie per la risposta. Ho capito che era solo un problema di scope :) – Eonil

6

stai toccando un nervo qui. Lo schema non ha una nozione standard molto chiara su come funzionano gli ambienti di primo livello. Perché? Perché gli standard Schema rappresentano un compromesso tra due gruppi di persone con idee molto diverse su come schema dovrebbe funzionare:

  • La folla interpretativo, che vede l'ambiente di alto livello, come si descrive in precedenza: un runtime hash-table in cui i collegamenti vengono aggiunti progressivamente man mano che l'interpretazione del programma procede.
  • Poi c'è il pubblico di compilation, che vede l'ambiente di primo livello come qualcosa che deve essere completamente computabile in fase di compilazione (cioè, un compilatore deve essere in grado di identificare in modo definitivo tutti i nomi che saranno associati nel livello più alto ambiente).

La domanda "come faccio a non definire una variabile" ha senso solo nel primo modello.

Si noti che il modello interpretativo, in cui i collegamenti di livello superiore di un programma dipendono da quali percorsi di codice vengono acquisiti, rende molto più difficile la compilazione efficiente del codice Scheme per molte ragioni. Ad esempio, in che modo un compilatore Scheme può richiamare una chiamata di procedura se il nome della procedura è un'associazione di livello superiore che potrebbe non solo cambiare durante il runtime, ma anche scomparire nel nulla?

Sono saldamente nel campo di compilazione qui, quindi quello che ti consiglierei è di evitare di scrivere codice che si basa sulla possibilità di aggiungere o rimuovere binding di livello superiore in fase di esecuzione, o anche che richiede l'uso di top -le variabili di livello (anche se spesso sono inevitabili). Alcuni sistemi Scheme (ad esempio, Racket) sono in grado di produrre codice compilato ragionevolmente buono, ma se si apportano tali presupposti li faranno saltare in questo senso.

+0

Oh bella spiegazione. Posso trattare * interpretative vs compilation * come * dynamic vs static * (al livello superiore)? – Eonil

+1

Sì, fondamentalmente. Per una compilazione efficiente, si desidera che tutti gli ambienti di primo livello siano noti staticamente. Ciò significa conoscere tutti i collegamenti esistenti al livello superiore e quali di essi sono soggetti a una mutazione in qualsiasi punto del programma. Qualsiasi binding di routine di livello superiore immutabile può quindi essere compilato come chiamate di funzione diretta e può essere facilmente sottolineato; le chiamate ai binding di livello superiore che possono essere mutate devono aggiungere una ricerca indiretta (poiché l'associazione può cambiare in fase di runtime) e potrebbe non essere facilmente integrata. –

0

Penso che la tua domanda non sia stupida. In AutoLISP è presente una variabile non definita (non definita) valore supposto apriori "nil" (anche se la variabile non esiste in memoria - significa - se non è in una tabella di variabili - allora il valore è "nil" - "falso") . Significa anche falso. Ed è anche una lista vuota. Se si programma un qualche tipo di funzione di lista di elaborazione, è abbastanza per fare test iniziale solo:

(if input-list ....) 

Quando si desidera ridefinisca in modo esplicito qualsiasi variabile, si può fare questo:

(setq old-var nil); or: (setq old-var()) 

Mi piace esso. La parola chiave "setq" significa "definire". Cosa c'è di meglio nelle variabili bounding e illimitate negli altri dialetti? Devi testare se esistono, se sono elenchi, hai bisogno di garbage-collector, non puoi non definire la variabile in memoria esplicitamente libera. A seguito di comando non può essere scritto se il "my-list" variabile non è definita:

(define my-list (cons 2 my-list)) 

Quindi penso che il modo in cui AutoLISP è per la programmazione molto meglio. Possibilità, che ho scritto, puoi usare lì. Sfortunatamente, AutoLISP funziona solo in alcuni sistemi grafici di ingegneria CAD.

0

Come indicato nelle altre risposte, non esiste un modo standard per manipolare lo spazio dei nomi in Schema. Per un'implementazione specifica potrebbe esserci una soluzione.

In Racket le variabili di livello superiore sono memorizzate in uno spazio dei nomi. È possibile rimuovere una variabile utilizzando namespace-undefined-variable.

Non c'è modo di rimuovere una variabile locale.

http://docs.racket-lang.org/reference/Namespaces.html?q=namespace#%28def.%28%28quote.~23~25kernel%29._namespace-undefine-variable%21%29%29

0

Scheme (R7RS) non ha modo standard compliant per rimuovere un legame di livello superiore.

Se si valuta una variabile non esistente, si ottiene un errore:

(eval 'a) 
; => ERROR: undefined variable: a 

Se si definisce, la variabile viene aggiunto per l'ambiente di livello superiore.

(define a 1) 
(eval 'a) 
; => 1 

Da ora qualunque cosa tu faccia, non otterrai un errore se accedi alla variabile.

Se si imposta su false, si otterrà falso:

(set! a #f) 
(eval 'a) 
; => #f 

Anche se si imposta su qualcosa di non specificato, è improbabile che si ottiene un errore:

(set! a (if #f #t)) 
(eval 'a) 
; => 

Ma Gli schemi possono disporre di un metodo non standard per rimuovere un'associazione di livello superiore. Schema MIT fornisce la funzione unbind-variable.

Problemi correlati