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 代码。
在执行 'leinuberjar' 命令后,我可以在生成的结果 JAR 文件中看到第三方 Clojure 库的编译类文件。

如果我在使用 'leinuberjar' 时加上 '-Dclojure.compiler.direct-linking=true' 选项,那么有可能我会破坏那些依赖于某些 _runtime_ 重绑定全局变量魔法的第三方库,因为直接链接可能会导致这种魔法消失吗?
动态变量不会进行直接链接。
明白

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

据我所知,启用 direct-linking 后,alter-var-root 会改变变量,但它的引用已经被编译,所以调用的位置不会受到影响,并继续使用编译后的直接函数调用

这是正确的吗?
by
— 可以断开库的连接
— 如何做到这一点?

是的,我很混淆,做得也不对。我的意思是,当整个代码库启用了直接链接时,与库交互时可能会出现问题。

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

    ;; 库
    
    (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}]
       ,,,
       )
...