gpt4 book ai didi

Clojure:如何避免对 map 获取中未找到的表达式进行评估

转载 作者:行者123 更新时间:2023-12-02 13:58:38 25 4
gpt4 key购买 nike

我有一张名为机器人的 map 。在查找 map 时,如果给定键的机器人不存在,我想创建一个。 clojure.core/getnot-found arg 似乎正是我所需要的。

但是,似乎 not-found 表达式是急切求值的。如何防止这种评估,以便仅在机器人不存在时才创建一个新机器人?

robot> (def robots {1 {:name "R2D2"}})
#'robot/robots


robot> (get robots 1)
{:name "R2D2"}

robot> (get robots 1 (println "damn it"))
damn it
{:name "R2D2"}

最佳答案

问题是这不是一个分支语句——它实际上需要在 not-found 槽中得到一个值,而不是一个形式或函数。所以你可以使用分支语句:

(if-let [r (get robots 1)] r (println "Beep boop"))

如果打字太多,你可以考虑一下:

(defmacro get-lazy
[map idx statement]
`(if-let [v# (get ~map ~idx)] v# ~statement))

user=> (get-lazy robots 1 (println "Oops!"))
{:name "R2D2"}

根据 A.Webb 的评论提示,我们得出以下宏。它使用与上面相同的方法,并且还可以处理包含 falsenil 值的映射。它也比在 map 上调用 contains?get 更快。不要使用错误的返回值 (false/nil) 来提示您该项目不存在,而是使用 get 的内置功能并检查“中永远不会出现的内容”狂野” map 。

(defmacro get-lazy
[map idx statement]
`(let [r# (get ~map ~idx ~::nil)]
(if (identical? r# ~::nil) ~statement r#)))

user=> (get-lazy {:idx 8} :idx (println "Yo."))
8
user=> (get-lazy {:coconuts :migration} :swallow (println "Who goes there?"))
Who goes there?
user=> (ns another.ns)
another.ns=> (user/get-lazy {:LUE ::nil} :LUE (println "42."))
:another.ns/nil

您可以避开宏并走功能路线:

(let [sentinel ::nil]
(defn lazyget
[map idx function]
(let [r (get map idx sentinel)]
(if (identical? r sentinel) (function) r))))

这在我的机器上有点慢。

关于Clojure:如何避免对 map 获取中未找到的表达式进行评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23197520/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com