elisp dealing with closure
I'm trying to write a macro that can generate a set of functions that I can use to access project directories in a more efficient fashion. If you look at the following macro, you should have a good idea what I'm trying to do.
(defmacro create-project-cmd (project-name project-dir &optional subdir-list)
(if (null subdir-list)
`(fset (intern ,project-name) #'(lambda () (interactive) (dired ,project-dir)))
`(dolist (dir ,subdir-list)
(fset (intern (con开发者_开发问答cat ,project-name "-" dir))
#'(lambda () (interactive) (dired (concat ,project-dir "/" dir)))))))
The problem here is the "dir" in the last line is supposed to bond to the "dir" in dolist clause. And since there is no closure in elisp, when I call a function that is generated, it will complain dir is void.
As you can see from the code, I have faked a closure for "project-dir". I can't fake it the same way for "dir". Even though lexical-let will make it work here, I'm trying to avoid it, since it has some memory issues, and I don't want to grow a habit of using it (maybe I'm too picky here).
I do not have a good way to handle this. Anyone have any good suggestions?
- How to overcome the lack of local variable for emacs lisp closure
- How do I do closures in Emacs Lisp?
- http://www.emacswiki.org/emacs/FakeClosures
Edit: If lexical-let is out, how about something like this:
(defmacro create-project-cmd (project-name project-dir &optional subdir-list)
(if (null subdir-list)
`(fset (intern ,project-name) #'(lambda () (interactive) (dired ,project-dir)))
(let ((fsets nil))
(dolist (dir subdir-list)
(add-to-list
'fsets
`(fset (intern (concat ,project-name "-" ,dir))
#'(lambda () (interactive) (dired (concat ,project-dir "/" ,dir))))))
`(progn ,@fsets))))
(create-project-cmd "projfoo" "projdir" ("foo" "bar" "baz"))
(symbol-function 'projfoo-bar)
(lambda nil (interactive) (dired (concat "projdir" "/" "bar")))
精彩评论