【问题标题】:Conditionally remove let-binding in lisp macro有条件地删除 lisp 宏中的 let-binding
【发布时间】:2016-07-23 21:57:48
【问题描述】:

如何有条件地删除在 lisp 宏中创建的 defun 中的 let 绑定?在这里,我想从生成的函数中删除第一个 let-bound 变量,但遇到了一个问题,我有一个 nil 留在 let 绑定中,导致错误。

例如,生成的函数使用letlet* 并且应该根据arg 删除第一个变量赋值。但是我写问题的方式来自用nil替换var1。我不知道如何摆脱零。

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

【问题讨论】:

  • 最简单的解决方法可能是使用,@(when arg '((var1 1)))cons 应该是函数调用吗?它被引用了,所以现在您还定义了一个名为cons 的变量。我觉得没必要。
  • macroexpand 是你的朋友。用它来找出你的宏调用扩展的内容。在这种情况下,它会告诉您相关部分扩展为 (let (cons nil (var2 ...))...), which binds a variable named cons` 并尝试绑定一个名为 nil 的部分。
  • 您的问题本身不是关于 Emacs Lisp 的问题。这是一个关于 Lisp 宏的问题。我添加了标签 lisp-macros,因为在 StackOverflow 上标签 macros 并不是真正的意思。

标签: emacs lisp-macros


【解决方案1】:

最简单的解决方法可能是使用,@(when arg '((var1 1))),@ 用于将列表拼接到该位置。由于WHEN 如果条件失败则返回NIL,并且NIL 与空列表相同,因此拼接会有效地忽略它。当条件成功时返回((var1 1)),并且(var1 1)被拼接解包。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-07
    • 1970-01-01
    • 2015-08-31
    • 2021-06-09
    • 2014-09-04
    • 2015-06-04
    相关资源
    最近更新 更多