请在Clojure 2024 状态调查中分享您的看法!

欢迎!有关如何使用本站的相关信息,请参阅关于页面。

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

哎呀,标题中有一个拼写错误(重复了 "single")

0 投票

评论来自:alexe Miller

case 中的空匹配列表看起来应该是一个错误 - 这可能应该导致编译失败而不是忽略?

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 投票

评论来自:alexe Miller

现在 () 不会匹配任何内容,因此对 () 失败不会破坏任何现有匹配的 case。

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

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

0 投票

评论来自:chrisblom

我并没有用它来匹配空列表,我是当从 DSL 生成 case 语句时遇到这个边缘情况的。
虽然这是一个病理情况,但我不同意它没有意义,此处的空列表 merepresents 没有其他选择,
因此,子句永远不会匹配,其结果表达式也永远不会运行。

我的观点是,现在(在 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(由chrisblom报告)
...