Clojure使用resolve时能否避免重复执行symbol lookup符号查找?
解决方案
- 方案1:使用
some->线程宏简化写法some->会在链式调用的任意步骤返回nil时直接终止执行并返回nil,刚好匹配你「非空才继续后续操作」的需求,全程仅会执行一次resolve:
;; 符号不存在时返回nil (some-> "A" symbol resolve deref) ;; 符号不存在时返回false (or (some-> "A" symbol resolve deref) false)
- 方案2:使用let绑定缓存resolve结果
如果你觉得宏的写法不够直观,直接用let存储resolve的返回值即可,从逻辑上避免重复调用:
(let [resolved-var (resolve (symbol "A"))] (if resolved-var @resolved-var false))
- 自定义安全解引用函数
Clojure标准库没有内置安全解引用的工具函数,你可以自己封装一个极简版本复用:
(defn safe-deref [v] (when (some? v) @v)) ;; 调用示例,不存在时返回nil,需要返回false则追加or即可 (or (safe-deref (resolve (symbol "A"))) false)
性能相关说明
编译器不会对两次resolve调用做公共子表达式消除优化,因为resolve的返回值依赖运行时的var定义状态,编译器无法假设两次调用返回结果一致,重复调用确实会产生额外开销。
如果你要执行大量同类处理,还可以对解析逻辑做缓存进一步提升性能:
;; 用memoize缓存字符串的解析结果,同一字符串只会执行一次resolve逻辑 (def cached-resolve (memoize (fn [s] (or (some-> s symbol resolve deref) false)))) ;; 后续直接调用即可 (cached-resolve "A")
内容的提问来源于stack exchange,提问作者LionelGoulet
相关产品推荐
相关产品推荐

