对于案例,这些表达案例的方法中哪种最好?

2024-04-17

这些都有效:

(defun testcaseexpr (thecase)
  (case thecase
    ('foo (format t "matched foo"))
    (bar (format t "matched bar"))
    ((funk) (format t "matched funky"))))

这三种表达方式中哪一个被认为是惯用方式?也许作为一个侧面,为什么它们都可以工作,而显然它们的语法并不相同。事实上,在其他上下文中它们具有完全不同的语义。一个列表(funk)当然与引用的原子不同,'foo。然而只是传递的话foo bar and funk一切都一样。


首先,请注意,这里实际上只有两个案例。'foo被读者扩展为(quote foo),所以你的代码相当于

(defun testcaseexpr (thecase)
  (case thecase
    ((quote foo) (format t "matched foo"))
    (bar         (format t "matched bar"))
    ((funk)      (format t "matched funky"))))

其中,第一情况和第三情况具有相同的结构;这keys该子句的一部分是对象列表。

也许这个问题是题外话,因为它要求的是“最好的”,而这可能主要是基于意见的。我同意中提出的观点wvxvw 的回答 https://stackoverflow.com/a/19977803/1281433,但我倾向于几乎完全使用您在第三种情况中展示的样式。我这样做有几个原因:

这是最一般的形式。

这是最一般的形式。在文档中case,我们在一个normal-clause ::= (keys form*) keys是键列表的指示符。这意味着像这样的子句(2 (print 'two))相当于((2) (print 'two))。你从来没有lose任何东西都可以通过使用列表而不是非列表来实现,但是如果您有一些带有多个对象的子句和一些带有单个对象的子句,那么所有这些子句都将具有一致的语法。例如,你可以有

(case operator
  ((and or) ...)
  ((if iff) ...)
  ((not)    ...))

搞砸就更难了。

这使得搞乱特殊情况变得更加困难t and otherwise。该文档说关于keys(强调):

键——对象列表的指示符。就本案而言, 符号t and otherwise不能用作按键指示符。到 将这些符号本身称为键、指示符(t) and (otherwise),必须分别使用。

在实践中,一些实现会让你使用t and otherwise as keys在普通条款中,即使这似乎不应该被允许。例如,在 SBCL 中:

CL-USER> (macroexpand-1 '(case keyform
                          (otherwise 'a)
                          (otherwise 'b)))


(LET ((#:G962 KEYFORM))
  (DECLARE (IGNORABLE #:G962))
  (COND ((EQL #:G962 'OTHERWISE) NIL 'A)
        (T NIL 'B)))

使用显式列表可以消除您要执行的操作的任何歧义。虽然t and otherwise被专门叫出来,keys是一个列表指示符,这意味着nil(一个原子和一个列表)需要一些特殊的考虑。下面的代码会产生a or b? (你能在不测试或检查规范的情况下判断出来吗?这种情况实际上在示例中突出显示。)

(case nil
  (nil 'a)
  (otherwise 'b))

它返回b。回来a,第一个普通子句必须是((nil) 'a).

结论

如果你总是确保keys是一个列表,您将:

  1. 最终得到看起来更一致的代码;
  2. 避免边缘情况错误(特别是如果您正在编写扩展为case); and
  3. 让你的意图更清晰。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对于案例,这些表达案例的方法中哪种最好? 的相关文章

  • 如何在 SLIME 的 REPL 中获得 Common Lisp 的语法高亮显示?

    我想学习 Common Lisp 并通过 emacs 包管理器安装了 emacs 24 3 和 slime 在 slime REPL 语法高亮中不起作用 另一方面 当我启动 Lisp Mode 在 slime REPL 中 时 表达式的值不
  • 与 emacs/slime 的其他 Lisp/Scheme 实现等效的 'lein swank'

    我一直在使用 emacs slime 来编码 lisp 但是使用 Clojure 我发现了 lein swank 我必须说它非常有用 因为我可以连接到运行 clojure 的服务器 其他 Lisp 实现怎么样 哪些 Lisp 实现提供了与
  • 如何使用 Common Lisp 获得列表的所有可能排列?

    我正在尝试编写一个 Common Lisp 函数 该函数将给出列表的所有可能排列 每个元素仅使用一次 例如 列表 1 2 3 将给出输出 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 我已经写过一些有用的东西 但它
  • 阅读宏:你用它们做什么? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Scheme/Racket有枚举操作吗?

    Scheme Racket 是否有相当于 Haskell 中的 a b 表示法的枚举表示法 在 Haskell 中 1 5 计算结果为列表 1 2 3 4 5 for list i in range 1 6 i sequence gt li
  • 如何理解clojure的lazy-seq

    我正在尝试理解 Clojurelazy seq运算符 以及惰性求值的一般概念 我知道这个概念背后的基本思想 表达式的求值被延迟 直到需要该值为止 一般来说 这可以通过两种方式实现 在编译时使用宏或特殊形式 在运行时使用 lambda 函数
  • Common Lisp 类型声明未按预期工作

    当我在 Common Lisp 中定义一个函数时 如下所示 defun foo n declare type fixnum n n 42 我期待一个像这样的电话 foo a 立即失败 但在调用时失败 是个declareform 不保证静态类
  • CLISP - 反转简单列表

    我必须反转简单 单维 列表的元素 我知道有一个内置的反向函数 但我不能用它来做这个 这是我的尝试 defun LISTREVERSE LISTR cond lt length LISTR 2 LISTR listr is 1 atom or
  • Common Lisp 中的(随机)不那么随机?

    好的 最后一个问题 我将用 Common Lisp 完成我的猜数游戏 D 每当游戏开始 或者在第一个游戏之后开始新游戏 时 都会调用以下函数 Play the game defun play If it s their first time
  • Lisp 中的数组与列表:为什么下面的代码中的列表要快得多?

    我在解决时得到了意想不到的结果欧拉计划中的问题 75 https projecteuler net problem 75 我的代码确实找到了正确的解决方案 但它的行为很奇怪 我的解决方案包括遍历毕达哥拉斯树 巴宁矩阵 https en wi
  • elisp:有没有办法获取当前 .el 模块的名称(如 C 中的 __FILE__ )?

    在我的 elisp 模块的顶部 我想做一些简单的事情 message concat Loading expand file name current elisp module 您可以使用变量load file name https www
  • F# 中的非类型化/类型化代码引用与宏卫生之间是否存在关系?

    我想知道 F 中的非类型 类型代码引用与宏系统的卫生之间是否存在关系 他们是否用各自的语言解决相同的问题 或者它们是不同的关注点 元编程方面是唯一的相似之处 即使在这方面 也存在很大的差异 您可以将宏的转换器视为从语法到语法的函数 就像您可
  • 在 Lisp 解释过程中,“读者”的任务是什么?

    我想知道 读者 在解释 编译 Lisp 程序期间的目的 或者更准确地说 是 读者 的任务 从我刚刚完成的问题前研究来看 在我看来 读者 特别是本例中的 Clojure 可以被视为 语法预处理器 它的主要职责是读取器宏和原始形式的扩展 所以
  • let* 和 set 之间的区别?在 Common Lisp 中

    我正在从事一个基因编程爱好项目 我有一个函数 宏设置 当以 setq setf 形式评估时 将生成一个如下所示的列表 setq trees make trees 2 gt x abs x 然后它将绑定到 lambda 函数
  • 宏扩展可以包含(声明...)表达式吗?

    Common Lisp Hyperspec 规定 宏形式不能扩展为声明 声明表达式必须显示为它们引用的形式的实际子表达式 我对 扩展到 的含义感到困惑 由于显而易见的原因 如下宏将不起作用 defmacro optimize fully d
  • 为什么在基于 Lisp 的语言中习惯上将许多右括号放在一行上?

    通常代码如下所示 one thing another thing arg1 f arg5 r another thing arg1 f arg5 r 为什么不喜欢这样 one thing another thing arg1 f arg5
  • 使用包阴影符号

    例如 我有这个包定义 它遮蔽了 COMMON LISP LISTEN defpackage shadows use common lisp shadow listen export listen 然后我想使用另一个包中的这个包 比如说 de
  • 有没有一种简单的方法可以使用 Common Lisp 中的 Python 库?

    在编写 Common Lisp 代码时我真正怀念的一件事是访问 Python 库 包括标准库和第三方模块 CLPython 提供了 Python 功能的有限子集 这阻止了大多数库的使用 因此这对我来说并不是很有用 我希望能够从 Common
  • 在 Common Lisp 中编写 Lambda 表达式

    我目前正在阅读 Paul Graham 的 ANSI Common Lisp 并且有一个关于编写 lambda 表达式的问题 我们是否需要在 lambda 表达式前面加上前缀 如果我在 REPL 中写这样的东西 它会工作得很好 gt lam
  • gensym 在 Lisp 中做什么?

    我听到一些同学谈论他们如何使用该功能gensym为此 我问他们它做了什么 甚至在网上查了一下 但我真的无法理解这个函数的作用是什么两者都不为什么或何时最好使用它 特别是 我对它在 Lisp 中的作用更感兴趣 谢谢你们 独特且未被拘禁的符号

随机推荐