让我的lisp代码更健壮

让我的lisp代码更健壮,lisp,common-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 >

亲爱的各位,我现在有一个初步的宏

(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
所以我现在被困在这一点上,我对Lisp宏有点陌生。我可以考虑使用
&rest
进行此扩展,但不知道如何使用,因此我需要您提供有关如何使此扩展正常工作的想法


非常感谢。

我假设您正在使用一些常见的Lisp实现

这种类型的参数解析不直接受支持。您认为必须自己解析参数是对的(您可以使用
(test&rest键和表单)
捕获测试,但是提取:ELSE和:THEN部分将由您决定

我不是超级(普通)Lisper,但您在这里发明的语法似乎非常不惯用。第一个提示是宏lambda列表不支持您想要的内容。此外,已经有相同长度或更短的原始字符输入的标准替代方案(通过使用类似于Emacs中的结构编辑器,可以稍微减少键入开销)


Common Lisp宏是非常强大的代码模板引擎,但这种特殊用法让我觉得您对Common Lisp中的标准样式和习惯用法不太熟悉。无论您使用哪种语言,“随大流”几乎总是一个好主意通过采用“本地”样式和习惯用法,而不是使用您更熟悉的其他语言的样式和习惯用法。

我假设您正在使用一些常见的Lisp实现

这种类型的参数解析不受直接支持。您认为必须自己解析参数是正确的(您可以使用
(test&rest键和表单)
捕获测试,但提取:ELSE和:THEN部分将由您决定

我不是超级(普通)Lisper,但您在这里发明的语法似乎非常不惯用。第一个提示是宏lambda列表不支持您想要的内容。此外,已经有相同长度或更短的原始字符输入的标准替代方案(通过使用类似于Emacs中的结构编辑器,可以稍微减少键入开销)


Common Lisp宏是非常强大的代码模板引擎,但这种特殊用法让我觉得您对Common Lisp中的标准样式和习惯用法不太熟悉。无论您使用哪种语言,“随大流”几乎总是一个好主意通过采用“本地”样式和习惯用法,而不是使用您更熟悉的其他语言的样式和习惯用法。

键机制仅适用于对。因此,您只有两条路径:继续使用对(您可以将列表用于then和else参数,并将这些列表放入程序),或者您拥有&REST上的解析器

以下是REST上的解析器(&R):

(defmacro keyif (test &rest rest)
  (loop with then? = t
        for arg in rest
        if (eq arg :then) do (setf then? t)
        else if (eq arg :else) do (setf then? nil)
        else if then? collect arg into then-list
        else collect arg into else-list
        finally (return `(if ,test (progn ,@then-list) (progn ,@else-list)))))

它在
rest
列表上循环,将参数收集到
then list
else list
中,具体取决于
then?
标志,当找到关键字
:then
:else
时,该标志会发生变化。另外,还支持多个then/else关键字,de假设
:then
错误。

键机制只在对上起作用。因此,您只有两条路径:继续使用对(您可以对then和else参数使用列表,并将这些列表放入PROGNs中),或者您拥有对&REST的解析器

以下是REST上的解析器(&R):

(defmacro keyif (test &rest rest)
  (loop with then? = t
        for arg in rest
        if (eq arg :then) do (setf then? t)
        else if (eq arg :else) do (setf then? nil)
        else if then? collect arg into then-list
        else collect arg into else-list
        finally (return `(if ,test (progn ,@then-list) (progn ,@else-list)))))

它在
rest
列表上循环,将参数收集到
then list
else list
中,具体取决于
then?
标志,当找到关键字
:then
:else
时,该标志会发生变化。另外,还支持多个then/else关键字,de假设
:then
错误。

Common Lisp中的循环宏有如下内容。(循环…如果(foo)那么执行…其他执行…)RainerJoswig,这就是为什么
loop
被一大群Lisper广泛憎恨的原因;它是标准中的一个核心宏,与语言其他部分的习惯用法完全不一致。然而,loop仍然是lisp宏系统强大的一个光辉的例子。@OpenLearner:有一些来自一些纯粹主义者和来自那些说它在某些复杂情况下没有得到充分规定的人,但实际的程序员要么使用它,要么使用其他东西(一些使用设计更好的,但更复杂的
迭代
).LOOP并不比其他建议的迭代工具差多少,这些工具与语言的其他部分也有很大的不同。与类似格式的工具相比,它与语言习惯用法的差异也小得多。Common Lisp中的LOOP宏有类似的功能。(LOOP…if(foo)then do…else do…)RainerJoswig,这就是为什么
loop
被一大群Lisper广泛憎恨的原因;它是标准中的一个核心宏,与语言其他部分的习惯用法完全不一致。然而,loop仍然是lisp宏系统强大的一个光辉的例子。@OpenLearner:有一些来自一些纯粹主义者和来自那些说它在某些复杂情况下没有得到充分规定的人,但实际的程序员要么使用它,要么使用其他东西(一些使用设计更好的,但更复杂的
迭代
).LOOP并不比其他建议的迭代工具差多少,它们与语言的其他部分也有很大的不同。与类似格式的东西相比,它与语言习惯用法的差异也小得多。
(defmacro keyif (test &rest rest)
  (loop with then? = t
        for arg in rest
        if (eq arg :then) do (setf then? t)
        else if (eq arg :else) do (setf then? nil)
        else if then? collect arg into then-list
        else collect arg into else-list
        finally (return `(if ,test (progn ,@then-list) (progn ,@else-list)))))