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

欢迎!请参阅关于页面,获取更多此如何运作的信息。

+2
编译器
编辑者

盲目启用直接链接可能会破坏库,而且我无法控制哪些变量受到影响,但我仍然想至少提高某些代码的性能。

以下是否可行?

(binding [clojure.core/*compiler-options* 
  {:direct-linking true}]
  ,,,
  )

以下是文档: https://docs.clojure.org/clojure.core/*compiler-options*

1 个回答

0

可能会破坏库

为什么?

重要的是,编译发生时这些编译器绑定被设置为何种状态。编译发生在加载时,因此我们关于这一点应该很聪明,但这将是聪明的。我认为在某个地方还有一个关于如何更直接地控制链接位置的问题。

"怎么做?"

在我看来,在反编译的代码中 + 根据 Clojure 文档,'direct-linking' 编译器键可以在可能的情况下启用函数直接调用,而不是通过 var 间接调用。

假设我有一些使用第三方 Clojure 库的 Clojure 代码。
使用 'lein uberjar',我可以看到我的结果 jar 文件中的第三方 Clojure 库的编译类文件。

如果我在使用 'lein uberjar' 时通过 '-Dclojure.compiler.direct-linking=true',那么我可能会破坏依赖于一些 _runtime_ 重绑定全局 var 魔法的第三方库吗?这个魔法可能会因为直接链接而消失?
动态变量不会被直接链接。
理解了

重复的 def 和 alter-var-root 呢?

据我所知,启用直接链接后,alter-var-root 会改变 var,但它的引用已经被编译,所以调用站不会被影响,并继续使用编译的直接函数调用。

正确吗?
— 可以破坏库
— 如何做到这一点?

是的,我感到困惑,而且设置错了。我的意思是,当整个代码库开启直接链接时,与库的交互可能会出现问题。

第一种情况可能不太可能发生,但库可能会期望用户以不同的方式实现协议,并重新定义一个实例,或者我们可能出于某种原因想要这么做。

    ;; 库
    
    (defprotocol MyProtocol
      (my-function [this]))
    
    (def my-instance (reify MyProtocol
                                            (my-function [this] (println "hello"))))
    
    
    ;; 应用程序
    
    ;; 我们无法重新定义 my-instance
    ;; 并且我们不能将其设置为 ^:redef,因为它在库中

第二种情况是我们正在开发库时忘记了标记一个变量为 ^:redef,应用程序将看不到其中的变化。

    ;; 库
    (def my-var 10)
    ;; 我们稍后尝试更新它,在所有内容都编译完成之后
    
    ;; 应用程序
    (defn use-var []
      (println my-var))

这两个例子可能是虚构的,我并没有一个具体的问题要回答“如何做以下操作?”,但直接链接仅在文档中简要介绍,并没有详细说明如何以细粒度方式处理,这就是为什么我问这个问题。

Andray Shotkin 检查了一下,显然这是可行的,代码确实直接链接,没有变量。

    (binding [*compiler-options* {:direct-linking false}]
      (clj-java-decompiler.core/decompile (fn []
                                            (seq (map :x [1 2 3])))))
    
    (binding [*compiler-options* {:direct-linking true}]
      (clj-java-decompiler.core/decompile (fn []
                                            (seq (map :x [1 2 3])))))
                                          
所以,我在这里贴出一个如何为一个命名空间启用直接链接的例子,以防万一。以防我完全忘记了这次对话,以后再查找直接链接。

    (ns my-namespace
     (:require [clojure.core :as core]))
    
    (binding [core/*compiler-options*
              {:direct-linking true}]
       ,,,
       )
...