请在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
:default)
=> :ok

但这个不行

(案例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

( funk.function )现在永远不会匹配任何内容,因此在 () 上失败不会破坏现有情况匹配的任何情况。

由于 Clojure 1.8 之前的版本中,只有在它不是唯一子句时才允许 case 中的 (),因此让编译器拒绝它可能会破坏现有代码。

但是,我想象的一个可能存在的情况是一个创建 case 并可能程序化创建空 case 列表的宏?

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

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