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

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

由于clojure <1.8中case中的()被允许(只是当它是唯一的子句时不允许),让编译器拒绝它可能会破坏现有的代码。

??我唯一能想到的情况是宏创建的case,并且可能编程地创建空case列表????

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

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