请在2024 年 Clojure 状态调查!中分享您的想法。

欢迎!请参阅关于页面了解有关此信息。

0投票
Clojure

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

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

返回 :none,但它失败并抛出了一个无用的异常:"未处理的 clojure.lang.ArityException: 传递给:core/max 的参数数量不正确 (-2)"

我期待 (case 1 () :a) 会失败并抛出 "java.lang.IllegalArgumentException: 没有匹配的条款",但相反,它也失败并抛出
"未处理的 clojure.lang.ArityException: 传递给:core/max 的参数数量不正确 (-2)"

这似乎不一致,因为当有其他选择时,传递空选项列表是可以的

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

如预期返回 :none

附带的补丁在进一步转换为 case* 之前删除了带有空测试列表的测试条款对,并添加了测试。

8 答案

0投票

评论者:chrisblom

唉,标题中有一个错误(重复的 "single")

0投票

评论者:alexmiller

case 中空匹配列表似乎应该是一个错误,也许它应该无法编译而不是被忽略?

0投票

评论者:chrisblom

当前支持在提供多个条款时只列出选项的空列表,因此空列表的编译失败将成为一个破坏性更改。

这在1.8版本中有效

(情况1
() :never-happens
1 :ok
:默认)
=> :ok

但这不行

(情况1
() :never-happens
:默认)
=> 抛出clojure.lang.ArityException: 给core/max传递的参数数量不正确(-2)。

只有在没有其他条款时才会失败,这对我来说似乎非常不一致。

0投票

评论者:bronsa

空列表在情况中没有任何意义,因为匹配文本空列表的正确方式是 (case () (()) :empty)。我认为使其不抛出任何错误没有任何价值,我的投票是通过每次在编译时对()的使用使case宏抱怨。

0投票

评论者:alexmiller

()永远不会匹配任何东西,因此针对 () 的失败不会破坏任何现有匹配。

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

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

0投票

评论者:chrisblom

我没有使用它来匹配空列表,我在从领域特定语言生成情况语句时遇到了这个特殊情况。
虽然这是一个病态的案例,但我不同意它没有意义,这里的空列表 simply 代表没有替代方案,
因此条款将永远不会匹配,并且其结果表达式将永远不会运行。

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

(case a
() :never-happens
1 :a
2 :b
:默认)

相当于(因为空列表永远不会匹配)

(case a
1 :a
2 :b
:默认)

(case a
() :never-happens
:默认)

提供了一个无用的错误。

我主张这应该相当于

(case a
:默认)

因为拒绝空列表作为情况语句的一般规则将是破坏性更改,
并且仅在没有其他条款存在时拒绝空列表是不一致的。

0投票

评论者:chrisblom

??()现在永远不会匹配任何东西,因此针对 () 的失败不会破坏任何现有匹配。??

因为cljure <1.8版允许在情况中的 (),所以让编译器拒绝它可能会破坏现有代码。

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

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

0投票
by
参考:https://clojure.atlassian.net/browse/CLJ-2164(chrisblom 招报)
...