请分享您的想法,参与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 这里这里

by
是的,为什么不呢?你能详细说明一下吗?
by
(评论
      (->> [1 2]
           (reduce (fn [acc v]
                     ((requiring-resolve 'clojure.set/union) acc #{v}))
             #{}))
      ;;=> #{1 2}
      )
by
重新展示 by
另外一点:tools.build大量使用requiring-resolve,所以我将其视为此类问题的官方解决方案,除非该fn的语义不适手当前情况 https://github.com/clojure/tools.build/blob/a9d0804ce8014088a7388e762034e9013922cacb/src/main/clojure/clojure/tools/build/api.clj#L126
+1 评分
by
编辑 by

我尝试了这个

(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表达式时,它并未被执行。为了在编译时执行,或许你可以调用一个宏'function'。

这确实有效。但我不太明白。你能解释一下吗?
当lambda定义作为函数编译时,它已被执行0次。因此,在第二行使用它时,require尚未完成。(我们仍然处于编译时间。)编译器需要知道什么是'c-set'。
我认为我已经理解了那里的问题。但我不明白为什么将require包裹在宏中能让`c-set`的使用工作。
唯一的区别是它在宏展开时执行。(宏通常是将代码转换成代码的函数,但在这个情况下,它被用于调用require的副作用。)如果你想用这样的定义构建一个AOT编译的库,这可能不是一个解决方案。在REPL中它是可行的。

注意:我不太明白你的最终用途。
by
谢谢。我想我需要思考一下宏展开的问题。=)

我的用例是在ClojureScript中(或者更准确地说是在nodejs环境中的SCI)中,我需要在promise解决后再延迟require。我还没有在那里测试这个解决方案,但是我将这样做并报告结果。目前我正在使用@Imre的解决方案,对于我的用例来说这是可以的,但我仍然想尝试一下。
by
对不起,但我的伪宏在这个情况下可能没有用,尽管它在REPL中给出了良好的结果。Imre是对的。
by
实际上它在我用例中是可行的。仅供参考。(我将坚持使用Imre的解决方案,但无论如何。)
...