Условно убрать let-привязку в макросе lisp

Как я могу условно удалить let-связывание в defun создан в макросе LISP? Здесь я хочу удалить первую переменную let-bound из результирующей функции, но сталкиваюсь с проблемой, когда у меня есть nil которая застревает в привязках let, вызывая ошибку.

Например, результирующая функция использует let или же let* и следует удалить первое назначение переменной в зависимости от arg, Но то, как я это написал, проблема заключается в замене var1 с nil, Я не уверен, как избавиться от нуля.

(cl-defmacro mac (cmd &optional arg)
  (let ((fn (intern (concat "fn-" cmd))))
    `(defun ,fn ()
       (interactive)
       (,(if arg 'let* 'let)
        (cons
         ,(when arg
            '(var1 1))
         (var2 (if (bound-and-true-p var1) (+ var1 1) 1)))
        (message "%s" var2)))))

(mac "fun")    ; Attempt to set constant: nil
(mac "fun2" t) ; no problem
;; (symbol-function 'fn-fun)
;; (symbol-function 'fn-fun2)
;; (fn-fun)
;; (fn-fun2)

1 ответ

Решение

Самый простой обходной путь, вероятно, заключается в использовании ,@(when arg '((var1 1))), ,@ используется для склеивания списка в позицию. поскольку WHEN возвращается NIL если условие не выполняется, и NIL такой же, как пустой список, соединение фактически игнорирует его. Когда условие успешно ((var1 1)) возвращается, и (var1 1) разворачивается сращиванием.

Другие вопросы по тегам