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

欢迎!有关如何使用本站的更多信息,请参阅 关于 页面。

0
Clojure

这与许多其他问题/问题单有关,但是我还没有找到专门针对这个问题的一个。

因为 :or 被解构到 not-found 值的 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
 
最佳答案

这是语言预期的行为。: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)))

你可以简化一些内容,只是尝试更清晰地表达。

感谢您的回答。这个页面(https://clojure.org/reference/special_forms#binding-forms)通过使用`init-expr`隐含地表明`:as`绑定优先于`:or`,但这并不是非常明确,没有任何示例显示它们不起作用。您愿意接受一个展示这种行为的补丁吗?
在这种情况下,我更倾向于有一个关于这个问题的issue,而不是一个PR。
by
好的,谢谢。
...