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

欢迎!请查看关于页面以获取更多关于如何使用本网站的信息。

+1
编译器

为什么我不能像这样在函数中使用require?

(comment
  (->> [1 2]
       (reduce (fn [acc v]
                 (require '[clojure.set :as c-set])
                 (c-set/union acc #{v}))
               #{})) ;=> Syntax error compiling at (lab/sandbox_playground.clj:31:18).
                     ;   No such namespace: c-set
  )

一开始我以为require需要放置在顶层。然而:这样做是可行的

(comment
  (do
    (require '[clojure.set :as c-set])
    (c-set/union #{1} #{2})) ;=> #{1 2}
  )

2 个答案

+3

被选中
 
最佳答案

为什么不用requiring-resolve?

编辑,详细信息

(comment
  (->> [1 2]
       (reduce (fn [acc v]
                 ((requiring-resolve 'clojure.set/union) acc #{v}))
         #{}))
  ;;=> #{1 2}
  )

根据与Peter(op)离线交谈,那段代码不工作是因为它被称为Gilardi场景。有关该问题的扩展描述可在ClojureDocs中找到。

在可能的情况下优先使用requiring-resolve的另一个原因是,从Clojure 1.11.1开始,require不是线程安全的。更多详细信息可以在这个问题中找到,以及在ClojureDocs的这里这里

是的,为什么不呢?你能详细说明一下吗?
(评论
      (->> [1 2]
           (reduce (fn [acc v]
                     ((requiring-resolve 'clojure.set/union) acc #{v}))
             #{}))
      ;;=> #{1 2}
      )

重新展示
还有一个要注意的是:tools.build大量使用requiring-resolve,所以我将其视为此类问题的官方解决方案,除非该fn的语义不适合当前情况 https://github.com/clojure/tools.build/blob/a9d0804ce8014088a7388e762034e9013922cacb/src/main/clojure/clojure/tools/build/api.clj#L126
+1

我尝试了这样

(defmacro require-macro [arg]
  (require arg))

(->> [1 2]
 (reduce (fn [acc v]
           (require-macro [clojure.set :as c-set])
           (c-set/union acc #{v}))
         #{}))

我认为当lambda被读取/编译时,它并未被执行。为了在编译时执行,或许您可以调用一个'macro'函数。

这实际上起了作用。但我还是不明白为什么。你能解释一下吗?
在lambda定义被编译为一个函数时,它已经被执行了0次。因此,在第二行使用它之前,尚未完成require的操作。(我们仍处于编译时。)编译器需要知道'c-set'是什么。
我想我已经明白了那些。但我还是不明白为什么把require放在宏中会使`c-set`的使用生效。
唯一的区别是它是在宏展开时执行的。(宏通常是从代码到代码的功能,但在这个案例中,它用于引发require的副作用。)如果你想要构建具有此类定义的AOT编译库,这可能不是你的问题的解决方案。在REPL中也有效。

注意:我对你的最终用途并不是很理解。
谢谢。我想我得考虑一下宏展开的时间。=)

我的用例是在ClojureScript中(或者更确切地说,是Nodejs环境中的SCI) 我需要将require延迟到promise解析后。我还没有在那个解决方案中尝试,但我将尝试并报告我的表现。目前我正在使用Imre的解决方案,这对我来说非常好,但我还是想尝试这个方案。
对不起,但我的伪宏的技巧在这个用例中可能没有用处,尽管它在REPL中给出了好的结果。Imre是对的。
实际上在我的用例中它确实起作用。仅供参考。(我将坚持使用Imre的解决方案,但是不管怎样。)
...