reale (non falsi) Le chiusure a Emacs 24.
Sebbene Emacs 24 presenta scavare lessicale quando la variabile lessicale vincolante ha valore t, il defun speciale la forma non funziona correttamente in contesti legati lessicalmente (almeno non in Emacs 24.2.1.) Questo rende difficile, ma non è impossibile da definire reale (non falso) chiusure.Per esempio:
(let ((counter 0))
(defun counting()
(setq counter (1+ counter))))
non funzionerà come previsto perché il contatore simbolo nel defun sarà legato alla variabile globale di questo nome, se ce n'è uno, e non la variabile lessicale definire nel let. Quando viene chiamata la funzione conteggio, se la variabile globale non esiste, allora ovviamente fallirà. Hoever se c'è una tale variabile globale viene aggiornata, il che probabilmente non è ciò che era previsto e potrebbe essere un bug difficile da rintracciare poiché la funzione potrebbe sembrare funzionare correttamente.
Il byte compilatore fa dare un avvertimento, se si utilizza defun in questo modo e presumibilmente il problema verrà affrontato in qualche futura versione di Emacs, ma fino ad allora la seguente macro può essere utilizzato:
(defmacro defun** (name args &rest body)
"Define NAME as a function in a lexically bound context.
Like normal `defun', except that it works correctly in lexically
bound contexts.
\(fn NAME ARGLIST [DOCSTRING] BODY...)"
(let ((bound-as-var (boundp `,name)))
(when (fboundp `,name)
(message "Redefining function/macro: %s" `,name))
(append
`(progn
(defvar ,name nil)
(fset (quote ,name) (lambda (,@args) ,@body)))
(if bound-as-var
'nil
`((makunbound `,name))))))
Se si definisce contando come segue:
(let ((counter 0))
(defun** counting()
(setq counter (1+ counter))))
che funzionerà come previsto e aggiornare la variabile legata lessicalmente contano ogni volta che viene richiamato, mentre restituisce il nuovo valore.
avvertimento: La macro potrebbe non funzionare correttamente se si tenta di defun ** una funzione con lo stesso nome di una delle variabili lessicalmente legate. Se si fa qualcosa del tipo:
(let ((dont-do-this 10))
(defun** dont-do-this()
.........
.........))
Non riesco a immaginare che qualcuno lo faccia effettivamente ma ne valeva la pena.
Nota: ho chiamato la macro defun **in modo che non si scontra con la macro defun * nel pacchetto cl, tuttavia non dipende in alcun modo su quella pacchetto.
Per quanto ho sentito, JavaScript è in realtà piuttosto funzionale. – Svante
Dipende dal punto di vista di una persona. Per me, se la maggior parte del codice nella lingua è imperativa, è imperativo. Qual è il caso qui. – vava
A partire dalla versione 24, Emacs ora ha uno scope lessicale. –