Real (sfałszować) zamknięć Emacs 24.
Chociaż Emacsa 24 ma leksykograficznego czerpania gdy zmienna słownikowa wiążące ma wartość t The defun specjalny formularz nie działa poprawnie w kontekście leksykalnym (przynajmniej nie w Emacs 24.2.1.) Utrudnia to, ale nie jest możliwe, ale definiuje rzeczywiste (nie fałszywe) zamknięcia.Na przykład:
(let ((counter 0))
(defun counting()
(setq counter (1+ counter))))
nie będzie działać zgodnie z oczekiwaniami, ponieważ licznik w defun symbol będzie związany z globalną zmienną o tej nazwie, jeżeli jest tylko jedna, a nie zmienne leksykalne określić w let. Gdy wywoływana jest funkcja zliczająca, jeśli zmienna globalna nie istnieje, to oczywiście zawiedzie. Zawsze, gdy istnieje taka globalna zmienna, jest ona aktualizowana, co prawdopodobnie nie jest zamierzone i może być trudnym do wykrycia błędem, ponieważ funkcja może działać prawidłowo.
Bajt kompilator nie dać ostrzeżenie, jeśli używasz defun w ten sposób i zapewne sprawa zostanie skierowana w jakiejś przyszłej wersji Emacsa, ale do tej pory następujące makro może być stosowany:
(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))))))
Jeśli zdefiniujemy licząc następująco:
(let ((counter 0))
(defun** counting()
(setq counter (1+ counter))))
będzie działać zgodnie z oczekiwaniami i zaktualizować leksykalnie związaną zmienną liczyć przy każdym wywołaniu, zwracając nową wartość.
zastrzeżenie: makro nie będzie działać prawidłowo, jeśli starają się defun ** funkcja o tej samej nazwie, jako jednego z leksykalnie związanych zmiennych. Tzn czy można zrobić coś takiego:
(let ((dont-do-this 10))
(defun** dont-do-this()
.........
.........))
Nie mogę sobie wyobrazić, że ktoś rzeczywiście robi, ale było warto wspomnieć.
Uwaga: nazwałem makro defun **tak aby nie kolidować z makro defun * w cl pakietu, jednak nie zależy w żaden sposób, że pakiet.
O ile słyszałem, JavaScript jest raczej funkcjonalny. – Svante
To zależy od punktu widzenia. Dla mnie, jeśli większość kodu w języku jest niezbędna, jest to konieczne. Tak jest w tym przypadku. – vava
Począwszy od wersji 24, Emacs ma teraz zakres leksykalny. –