簡體   English   中英

如何在Clojure中在運行時序列化函數?

[英]How can I serialize functions at runtime in Clojure?

有沒有辦法在Clojure中在運行時序列化函數? 我希望能夠以序列化格式通過線路發送無狀態(但不是純粹的)功能(可能是edn,但我對任何事情都開放)。


例如...

如果我在函數上運行prn-str ,我就得不到我期望/想要的東西。

user=> (def fn1 (fn [x] (* x 2)))
#'user/fn1
user=> (def data {:test 1 :key "value"})
#'user/data
user=> (defn fn2 [x] (* x 2))
#'user/fn2
user=> (prn-str fn1)
"#object[user$fn1 0x28b9c6e2 \"user$fn1@28b9c6e2\"]\n"
user=> (prn-str data)
"{:test 1, :key \"value\"}\n"
user=> (prn-str fn2)
"#object[user$fn2 0x206c48f5 \"user$fn2@206c48f5\"]\n"
user=> 

我希望/期望這樣的事情:

user=> (prn-str fn2)
"(fn [x] (* x 2))\n"

或者可能,

user=> (prn-str fn2)
"(defn fn2 [x] (* x 2))\n"

你必須使用quote'以防止評估和eval強制評估:

(def fn1 '(fn [x] (* x 2)))
(prn-str fn1) ;;=> "(fn [x] (* x 2))\n"
((eval fn1) 1) ;;=> 2

你基本上有兩個選擇:

  • 傳遞源代碼(存儲為clojure數據的s表達式)
  • 傳遞jar文件並在另一側加載它們。

對於第一個選項,您在編譯函數時保存源 (幾乎總是在定義時),然后將相同的源表達式傳遞給另一台計算機並讓它編譯相同的東西。 所以首先你可以制作一個表達式的向量:

(domain-functions '[(defn foo [x] x)
                    (defn bar [y] (inc y)]

然后你可以將它存儲到一個數據庫中,每個客戶端都可以傳遞它來read ,然后它們都將具有相同的功能。

第二個選項取決於每次定義一個函數時它會在/ target目錄中生成一個類文件然后加載它。 然后,您可以同步此目錄並在另一側加載它們。 這種方法當然是完全瘋狂的,盡管人們在這里做瘋狂的事情。 我推薦第一種方法


並作為個人說明:

我現在正在用datomic做這個,並且我已經采用了使用宏將git-hash放入函數名的做法,所以我絕對清楚地知道,當我調用一個函數時,我得到了我看到的相同函數在編輯器中。 當運行所有來自同一個DB的實例時,這會讓您高枕無憂。

Flambo是Spark的Clojure包裝器,它使用serializable-fn庫來序列化函數(Spark需要這些函數)。 Sparkling是Spark的另一個包裝器,它通過這個實現Java接口Serializable的Java抽象類使用本機Clojure函數。

你可以使用clojure.repl/source

(with-out-str (source filter))

得到一個字符串,或

(read-string (with-out-str (source filter)))

得到一個clojure列表。

真的有一個好方法,並且有充分理由簡單地將一個函數發送到另一台計算機或將其存儲在DB中會導致很多問題,其中最重要的是該函數可能需要其他未啟用的函數另一端。

更好的想法是堅持使用數據。 而不是編寫函數,將函數的名稱寫為事件,然后甚至可以通過讀取數據的任何內容來翻譯。 堅持使用數據,這是慣用的方式。

在某些時候,它不再是Clojure,所以我們可以任意地從源頭到機器指令往返的期望有點偏離。

我們應該能夠將函數序列化為字節數組並通過線路發送。 我懷疑你需要獲取函數的java.lang.Class對象,然后通過java.lang.instrument.ClassFileTransformer傳遞它來獲取字節。 一旦你有了那些,你可以將它們傳遞給遠程jvm上友好的java.lang.ClassLoader

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM