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

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

0
Clojure

不可能使用包含单个空选项序列的case,或者使用包含单个选项序列和默认子句的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

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

由于在clojure 1.8之前(只是不是当它是唯一条款时),允许使用()作为case表达式的情形,让编译器拒绝这种情况可能会破坏现有的代码。

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

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

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