Как я могу создать `with-eval-after-load-all` в Emacs Lisp? - PullRequest
2 голосов
/ 30 июня 2019

Я пытаюсь создать что-то похожее на with-eval-after-load за исключением того, что тело оценивает после того, как все функции были предоставлены.Кроме того, список функций должен быть предоставлен во время выполнения.

Например, я хочу что-то вроде

(setq feature-list '(a b))
(something feature-list (message "a and b both provided"))

, где это выполняет функциональность, эквивалентную

(with-eval-after-load 'a
  (with-eval-after-load 'b
    (message "a and b both provided")))

Предоставлениесписок во время выполнения кажется сложной частью.Без этого требования я мог бы написать макрос:

(defmacro eval-after-load-all (features body)
  (if (null features)
      body
    `(with-eval-after-load (quote ,(car features))
       (eval-after-load-all ,(cdr features) ,body))))

и передать список с помощью:

(eval-after-load-all (a b) (message "a and b both provided"))

Но если передать его feature-list, он будет использовать буквенные символы "list ".

Я попытался определить рекурсивную функцию:

(defun eval-after-load-all (features body)
  (if (null features)
      body
    (with-eval-after-load (car features)
      (eval-after-load-all (cdr features) body))))

Но когда я вычисляю

(eval-after-load-all feature-list (message "a and b both provided"))
(provide 'a)
;; (provide 'b)

Это вызывает ошибку при вызове (provide 'a)жаловаться на void-variable body в шаге рекурсивного вызова (т. е. последнее выражение в функции).Эта сфера смущает меня.Почему body здесь пусто?

Я также пытался обернуть макрос в функцию, чтобы я мог передать ей вычисленные аргументы:

(defun macro-wrapper (features body)
  (eval-after-load-all features body))

, но это вызывает жалобу при определении функции, чтоfeatures это не список: wrong-type-argument listp features.

1 Ответ

0 голосов
/ 17 июля 2019
  1. Вы не можете использовать символ features в качестве аргумента, поскольку это (я цитирую документ features):

    Список символов, которые являются особенностями исполнения Emacs. Используется featurep и require и изменено provide.

  2. Следующий код для eval-after-load-all работает как положено. Он получен из определения вашей рекурсивной функции.
    Я добавил оценку формы как функцию или как выражение с помощью funcall или eval, соответственно, я использовал обратную кавычку для лямбда-выражения и ввел цитирование для списка и выражения в сгенерированном лямбда-выражении.
(defun eval-after-load-all (my-features form)
  "Run FORM after all MY-FEATURES are loaded.
See `eval-after-load' for the possible formats of FORM."
  (if (null my-features)
      (if (functionp form)
      (funcall form)
    (eval form))
    (eval-after-load (car my-features)
      `(lambda ()
     (eval-after-load-all
      (quote ,(cdr my-features))
      (quote ,form))))))
...