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

哎,标题(重复“单个”)有误

0

评论由: alexmiller

在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

评论由: alexmiller

() 现在永远不会匹配任何东西,所以关于 () 的失败不会破坏任何现有的匹配 case。

我想象得到的一种情况是,一个创建 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 的 () 被允许(但是不能作为唯一的子句),但让编译器拒绝它可能会导致现有的代码出现破坏。

尽管如此,我想象得到的一个可能存在的情况是创建 case 并可能用来递归地创建空 case 列表的宏??

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

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