lisp - 让我的 lisp 代码更健壮

标签 lisp common-lisp

亲爱的大家,我现在有了一个初步的宏

(defmacro key-if(test &key then else)
  `(cond (,test
          ,then)
         (t,else)))

它现在可以正常工作了

> (key-if (> 3 1) :then 'ok)

OK

> (key-if (< 5 3) :else 'ok)

OK

> (key-if (> 3 1) :else 'oops)

NIL

> (key-if (> 3 1) :else 'oops :then 'ok)

OK

现在我想扩展它一点,这意味着我想有任意数量的参数后跟 :then:else (关键字),所以它会像

> (key-if (> 3 1) :then)

NIL

> (key-if (> 3 1) :else 'oops :then (print 'hi) 'ok)

HI

OK

所以我现在停留在这一点上,我对 Lisp 宏有点陌生。我可以考虑将 &rest 用于此扩展,但不知道如何操作,所以我真的需要您提供有关如何使此扩展正常工作的想法。

非常感谢。

最佳答案

我假设您正在使用一些 Common Lisp 实现。

the standard lambda lists used by DEFMACRO 不直接支持这种参数解析风格.你认为你必须自己解析参数是正确的(你可以使用 (test &rest keys-and-forms) 来捕获 TEST,但是提取 :ELSE 和 :THEN 部分将是正确的给你。

我不是 super (Common-)Lisper,但您在这里发明的语法似乎非常不合时宜。第一个提示是宏 lambda 列表不支持你想要的。此外,已经有标准的替代方案,其输入的原始字符长度相同或更短(通过使用 Emacs 中的 paredit 等结构编辑器可以减少输入开销)。

(key-if blah :then foo bar)                       ; multiple then, no else
(when blah foo bar)                               ; standard

(key-if blah :else baz quux)                      ; no then, multiple else
(unless blah baz quux)                            ; standard

(key-if blah :then foo :else baz quux)            ; one then, multiple else
(if blah foo (progn baz quux))                    ; standard
(cond (blah foo) (t baz quux))

(key-if blah :then foo bar :else baz)             ; multiple then, one else
(if blah (progn foo bar) baz)                     ; standard
(cond (blah foo bar) (t baz))

(key-if blah :then foo bar :else baz quux)        ; multiple then, multiple else
(if blah (progn foo bar) (progn baz quux))        ; standard
(cond (blah foo bar) (t baz quux))                ; even shorter

(key-if blah :else baz quux :then foo bar)        ; multiple else before multiple then
(if (not blah) (progn baz quux) (progn foo bar))  ; only standard variation that is longer
(cond ((not blah) baz quux) (t foo bar)           ; standard, shorter

Common Lisp 宏是非常强大的代码模板引擎,但这种特殊用法让我觉得您只是不太适应 Common Lisp 中的标准样式和习语。无论您使用哪种语言,采用“本地”风格和习语“顺其自然”几乎总是一个好主意,而不是从您更熟悉的其他语言中引入风格和习语。

关于lisp - 让我的 lisp 代码更健壮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1774360/

相关文章:

common-lisp - Lisp 没有反转我的列表

function - can if 是一个适当的函数而不是一个特殊的形式

arguments - Common Lisp - 给出 &rest 列表作为参数

loops - 理解循环宏扩展

macros - 编写破坏性的宏或函数,如 incf?

lisp - 如何在 LISP 中将算术运算符作为函数参数传递?

lisp - 如何在 Windows 中安装 gtk-cffi?

macros - 方案宏的优点是什么?

lisp - 在 maxima 中使用 lisp 代码

lisp - 在 Lisp (CLOS) 中访问槽的问题