How to overcome the lack of local variable for emacs lisp closure
I'm now studying Emacs Lisp from the reference manual and Common Lisp from a LISP Book.
from the Common Lisp book
>> (setf power-of-two
(let ((previous-power-of-two 1))
#'(lambda ()
(setf previous-power-of-two
(* previous-power-of-two 2)))))
>> (funcall power-of-two)
2
>> (funcall power-of-two)
4
>> (funcall power-of-two)
8
The function wo开发者_JAVA百科n't work in Emacs Lisp because of its dynamic binding behavior.
I wonder if it is possible to implement the same function in Emacs Lisp without introducing a global variable ?
Update:
By now, Emacs 24 has been officially released, and it supports lexical binding without using lexical-let
, when the buffer-local variable lexical-binding
is non-nil. See also M-: (info "(elisp) using lexical binding")
and pokita's answer.
You can use lexical-let
from the Common Lisp Extensions (the "CL package"):
elisp> (require 'cl)
cl
elisp> (setf power-of-two
(lexical-let ((previous-power-of-two 1))
#'(lambda ()
(setf previous-power-of-two
(* previous-power-of-two 2)))))
(lambda
(&rest --cl-rest--)
(apply
(lambda
(G175638)
(set G175638
(*
(symbol-value G175638)
2)))
'--previous-power-of-two-- --cl-rest--))
elisp> (funcall power-of-two)
2
elisp> (funcall power-of-two)
4
elisp> (funcall power-of-two)
8
I've also heard about a lexbind branch of GNU Emacs.
Emacs24 from bzr now supports lexical binding out of the box; it just isn't activated by default since there are many packages which still deliberately or inadvertently depend on dynamical scoping. Your above code should work just fine in Emacs24 in a buffer where the variable 'lexical-binding' is set to 't'.
See this page: http://www.emacswiki.org/emacs/FakeClosures
another solution using Emacs' unintern symbol:
ELISP> (setf power-of-two
(let ((p (make-symbol "previous-power-of-two")))
(set p 1) (list 'lambda '()
(list 'setf p
(list '* p 2)))))
ELISP> (funcall power-of-two)
2
ELISP> (funcall power-of-two)
4
ELISP> (funcall power-of-two)
8
精彩评论