Clojure编译时

Clojure编译时,clojure,compilation,leiningen,Clojure,Compilation,Leiningen,我第一次测试Clojure,想编写一个简单的websocket客户端应用程序。我已经找到了库并使代码正常工作(使用lein run)。但是,将代码编译到jar中(使用lein-jar或lein-uberjar会卡住或需要很长时间(在~1h后中止)) 步骤: lein新应用测试 修改的src/testing/core.clj和project.clj(见下文) leinjar(或leinuberjar) 为了简单起见,我有一段非常简单的代码,它已经需要很长时间才能编译成jar: (ns testin

我第一次测试Clojure,想编写一个简单的websocket客户端应用程序。我已经找到了库并使代码正常工作(使用
lein run
)。但是,将代码编译到jar中(使用
lein-jar
lein-uberjar
会卡住或需要很长时间(在~1h后中止))

步骤:

  • lein新应用测试
  • 修改的src/testing/core.clj和project.clj(见下文)
  • leinjar
    (或
    leinuberjar
  • 为了简单起见,我有一段非常简单的代码,它已经需要很长时间才能编译成jar:

    (ns testing.core
      (:gen-class))
    
    (require '[gniazdo.core :as ws])
    
    (def socket
        (ws/connect
                "wss://some.url.com/"))
    
    (defn -main
      "I don't do a whole lot ... yet."
      [& args]
      (ws/close socket))
    
    project.clj:

    (defproject testing "0.1.0-SNAPSHOT"
      :description "FIXME: write description"
      :url "http://example.com/FIXME"
      :license {:name "Eclipse Public License"
                :url "http://www.eclipse.org/legal/epl-v10.html"}
      :dependencies [[org.clojure/clojure "1.8.0"]
                     [stylefruits/gniazdo "1.0.1"]]
      :main ^:skip-aot testing.core
      :aot [testing.core]
      :target-path "target/%s"
      :profiles {:uberjar {:aot :all}})
    
    运行
    lein jar的输出

    $lein jar
    Compiling testing.core
    2017-12-11 14:15:14.813:INFO::main: Logging initialized @1352ms
    

    再也没有了。这是正常的行为(编译需要很长时间)还是我遗漏了什么?Clojure看起来很有趣,但如果编译这样一个小程序也需要几个小时,那么在我的情况下,部署可能会是一个问题。

    当该命名空间提前编译时(
    :aot[testing.core]
    ,在您的project.clj中),在编译过程中会对该代码进行评估:

    (def socket
      (ws/connect "wss://some.url.com/"))
    
    这可能是导致绞刑的原因。编译器永远不会从这一点出发,因为它已经进行了阻塞调用

  • 如果不需要(而且可能不需要),可以删除
    :aot
    指令。我认为在创建一个新的Leiningen项目时,这可能是一个有点令人困惑的默认设置

  • 您可以做一些类似于将插座/接头包裹在

    然后,
    deref
    /
    @
    在需要该值的任何位置执行该操作。这只会延迟对
    ws/connect
    的评估,直到您询问


  • 要么:1。不要在顶层连接或:2。不要AOT您的
    testing.core
    命名空间。你认为连接应该如何存储在JAR中?我不确定我是否理解正确:AOT编译实际上执行代码,而不是创建表示套接字定义的字节码?在这种情况下也可以:(defnsocket[url](ws/connecturl))@Moe是的,编译clojure代码的唯一方法是执行它所在的名称空间。
    (def socket (delay (ws/connect "wss://some.url.com/")))