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

欢迎!请查看 关于 页面,了解更多关于如何使用本站的信息。

0
Clojure

这与其他一些问题/bug 报告有关,但我没有找到专门针对这一点的。

因为 :or 分解为 get 调用中分解的键/符号等的缺失值,如果您用 :as 绑定一个对象并且在 :or 中包含默认值,对象将不具有这些默认值。

(defn example [{:keys [a b]
                :or {a 1 b 2}
                :as opts}]
  (println a b opts))

(example {:a 5})
;=> 5 2 {:a 5}

这导致我们代码库中出现了微妙的错误,我们原本期望有默认值,但实际上却没有。或者我们使用了 {:pre [some-pred]} 来检查一个不变性,当我们修改函数以使用 :as 并包含特定值时,该不变性被违反。

要合并它们,您需要先构建映射,然后进行 opts (conj defaults-map opts),但这需要对键/符号/字符串进行第二次迭代,只选择在 :or 映射中的名称,并且需要创建另一个映射,或者可能反复调用 assoc

我认为这是可行的,但编写起来可能会有些麻烦。

我想知道,这是否只是为了信息发布,或者在请求改变 Clojure 吗?

(改变分解中 :or 的行为将会是一个破坏性的语言更改 —— :as 特殊绑定原始映射值到符号)

编辑了
我希望对其进行更改。我觉得它很混乱,我在教Clojure时,这种不自然和令人惊讶的行为在学生们中也出现了。但预计大多数请求都会被拒绝,因为Clojure的大多数现有行为都是固定的。最好是检查一下。

1 个答案

+1

被Noah选中
 
最佳答案

这是语言故意实现的行为::as关于分解时提供的值。:keys或其它分解是关于绑定值。:or是关于提供缺失绑定的值的默认值。如果您有“始终包含”的默认值,那么我想您想在分解之前这样做,例如:

(defn example [opts]
  (let [defaults {:a 1 :b 2}
        defaulted-opts (merge defaults opts)
        {:keys [a b]} defaulted-opts]
    (println a b defaulted-opts)))

您可以将这部分内容合并,只是尝试使其更明确。

感谢您的回答。在这个页面中(通过使用`init-expr`)暗示了`:as`绑定优先于`:or`,但并不明确,并且没有示例显示它们不起作用。您是否会接受一个显示这种行为的补丁?
在这种情况下,我更希望有一个关于这个问题的issue,而不是PR
好的,谢谢。
...