首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Clojure:如何避免在map get中使用未找到的表达式

Clojure:如何避免在map get中使用未找到的表达式
EN

Stack Overflow用户
提问于 2014-04-21 12:33:11
回答 2查看 103关注 0票数 2

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

但是,not-found表达式似乎被急切地计算出来了。我如何才能防止这种评估,以便我创造一个新的机器人,只有当一个不存在?

代码语言:javascript
复制
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"}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-04-21 13:17:27

我完全同意Timothy Dean's answer,但是如果映射中有false或nil值,他的实现就不能工作。

以下是更精确的解决方案:

代码语言:javascript
复制
(if (contains? robots 1)
  (get robots 1)
  (println "Beep boop"))

还有奇特的宏:

代码语言:javascript
复制
(defmacro get-lazy [map key not-found]
  `(let [map# ~map
         key# ~key]
    (if (contains? map# key#)
      (get map# key#)
      ~not-found)))

我正在使用let消除两次引起某些副作用的可能性,例如:

代码语言:javascript
复制
(get-lazy {1 false}
          (do (println "Side effect") 1)
          (println "Oops!"))
票数 3
EN

Stack Overflow用户

发布于 2014-04-21 13:00:04

问题是,这不是一个分支语句-它实际上希望在not-found槽中有一个值,而不是一个形式或函数。因此,您可以使用分支语句:

代码语言:javascript
复制
(if-let [r (get robots 1)] r (println "Beep boop"))

如果打字量太大,你可能会觉得很花哨:

代码语言:javascript
复制
(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值的映射。它也比在地图上调用contains?get更快。不要使用假返回值( false /nil)提示您该项不存在,而是使用get的内置功能,并检查“野生”映射中永远不会出现的内容。

代码语言:javascript
复制
(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

您可以避开宏,选择功能路线:

代码语言:javascript
复制
(let [sentinel ::nil]
  (defn lazyget
   [map idx function]
   (let [r (get map idx sentinel)]
      (if (identical? r sentinel) (function) r))))

这在我的机器上慢了一点。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23197520

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档