2024 Clojure 状态调查! 分享您的想法。

欢迎!请参阅 关于 页面以了解更多关于这里的工作方式的信息。

0 投票
Clojure

无法使用单个空选项序列或单个选项序列和默认情况的 case。

我预期
bq. (case 1 () :a :none)

返回 :none,但它会失败并抛出一个无用的异常:"Unhandled clojure.lang.ArityException: Wrong number of args (-2) passed to: core/max"

我预期 (case 1 () :a) 会失败并抛出 "java.lang.IllegalArgumentException: No matching clause",但事实上它也会失败并抛出
"Unhandled clojure.lang.ArityException: Wrong number of args (-2) passed to: core/max"

这似乎不一致,因为当存在其他替代方案时,传递空列表选项是可以的

bq. (case 1 () :a 2 :b :none)

如预期返回 :none

附加的补丁在转换成 case** 之前移除了测试-条款对中具有空测试列表,并添加了测试。

8 答案

0 投票

评论者:chrisblom

哦,标题中(重复了“单个”)有打字错误

0 投票

评论者:alexmiller

case 中的空匹配列表似乎应该是一个错误 - maybe 这应该失败编译而不是忽略?

0 投票

评论者:chrisblom

在给定多个子句时,目前支持空选项列表,因此对空列表编译失败将是一个破坏性的变化。

这在1.8版本中是可行的

(case 1
() :never-happens
1 :ok
):default)
=> :ok

但这却不成立

(case 1
() :never-happens
):default)
=> 抛出 clojure.lang.ArityException: 传递给 core/max 参数数量错误 (-2)

只有在没有其他子句的情况下才会失败,这在我看来非常不一致。

0 投票

评论者:bronsa

在case中,空列表没有任何意义,因为匹配一个字面空列表的正确方法是 (case () (()) :empty)。我不认为使其不抛出任何错误有任何价值,我的建议是每当使用空白括号时,在编译时让case宏报错

0 投票

评论者:alexmiller

现在,空白括号不会匹配任何内容,所以对空白括号报错不会破坏任何现有匹配的case。

我想象的唯一可能的情况是,一个创建case的宏可能以编程方式创建一个空案例列表?例如

(defmacro make-case [xs] `(defn ~'foo [e#] (case e# ~xs "matched" "nope")))

0 投票

评论者:chrisblom

我并没有用它来匹配空列表,我在从DSL生成case语句时遇到了这个角落案例。
虽然这是一个病态的案例,但我不同意这是没有任何意义的,这里的空列表仅代表没有替代方案,
因此这个匹配子句将永远不会匹配,它的结果表达式也不会执行。

我的观点是,现在(在clojure 1.8中)这是允许的

(case a
() :never-happens
1 :a
2 :b
):default)

作为一个空列表永远不会匹配的例子)

(case a
1 :a
2 :b
):default)

但是

(case a
() :never-happens
):default)

给出一个没有信息的错误。

我争论的是它应该是等效的

(case a
):default)

因为拒绝在case语句中一般使用空列表将是一个破坏性的变化,
而且只在没有其他子句存在时拒绝空列表是不一致的。

0 投票

评论者:chrisblom

??() 现在永远不会匹配任何内容,所以在 () 上失败不会破坏任何现有的匹配案例。??

在 Clojure <= 1.8 中,case 级别只允许 ()(当它不是唯一条款时),让编译器拒绝它可能会破坏现有的代码。

??但我能想象存在的一种情况是,一个创建 case 并可能以编程方式创建空 case 列表的宏??

这正是我遇到这个问题的原因

0 投票
参考:[https://clojure.atlassian.net/browse/CLJ-2164](https://clojure.atlassian.net/browse/CLJ-2164)(由 chrisblom 报告)
...