Элисп, занимающийся закрытием - PullRequest
0 голосов
/ 16 сентября 2011

Я пытаюсь написать макрос, который может генерировать набор функций, которые я могу использовать для более эффективного доступа к каталогам проектов. Если вы посмотрите на следующий макрос, у вас должно быть хорошее представление о том, что я пытаюсь сделать.

(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 (concat ,project-name "-" dir))
               #'(lambda () (interactive) (dired (concat ,project-dir "/" dir)))))))

Проблема здесь в том, что «dir» в последней строке должно быть связано с «dir» в предложении dolist. И поскольку в elisp нет замыкания, когда я вызываю генерируемую функцию, он будет жаловаться, что dir is void.

Как видно из кода, я подделал закрытие для "project-dir". Я не могу притворяться так же, как "dir". Даже при том, что лексический-let заставит это работать здесь, я пытаюсь избежать этого, так как у него есть некоторые проблемы с памятью, и я не хочу вырабатывать привычку использовать его (возможно, я слишком привередлив здесь).

У меня нет хорошего способа справиться с этим. У кого-нибудь есть хорошие предложения?

1 Ответ

2 голосов
/ 16 сентября 2011

Редактировать: Если лексический-let отсутствует, как насчет чего-то вроде этого:

(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")))
...