我正在研究一個需要能夠從shell命令行讀取Clojure代碼的Clojure應用程序。該應用程序具有一個-main
函數,該函數讀取在包含單個Clojure表單的命令行上傳遞的字符串,並將該字符串傳遞給Clojure函數load-string
,該函數解析字符串並執行代碼。這使用lein run
和使用uberjar成功運行。如何在初始編譯時間後使命名空間別名可用?
我發現如果名稱空間爲required
位於包含-main
的文件頂部,則在命令行傳遞的代碼可以包含完全限定的名稱空間名稱。例如,如果源文件與
(ns popco.core.popco
(:require [popco.core.reporters :as rpt]))
開始然後我通過在命令行上的字符串可以通過popco.core.reporters/ticker
引用我的功能ticker
。但是,我不能使用別名rpt
。如果我通過rpt/ticker
提及ticker
,我會發現一個例外:java.lang.RuntimeException: No such namespace: rpt
。
我猜這是因爲別名只在編譯時可用,只有一個編譯時間。由於load-file
編譯代碼字符串的時間是源文件編譯完成後的時間,因此rpt
不再可用作別名。
允許我使用命名空間別名的解決方案是在-main
內複製文件頂部的require
s(我希望在repl中運行時使用)。然而,我可能需要包含幾個名稱空間,當然,重複代碼是不可取的。
有沒有另一種解決方案?某種方法可以定義一次別名,在repl中運行時以及從命令行運行代碼時都可以使用別名? (編輯:上面編譯時間的分析不能完全正確 - 也許我不懂Clojure彙編(嗯,其實我不懂Clojure彙編!)解決方案在上面兩段中提到的使用require
語句在-main
中的原始源代碼中,不僅使用傳遞給load-file
的字符串,所以require
在編譯-main
時得到編譯,我想,這將在與我假設源文件的頂部,但是如果代碼被輸入到-main
的定義中,-main
中的代碼在文件頂部的別名範圍內,但如果通過load-file
引入代碼,則代碼不在其範圍內。通過load-file
在(require '[popco.core.reporters :as rpt])
字面上是在-main
的源代碼中的別名範圍內。爲什麼?)
感謝您的詳細解釋。非常有趣,也很有幫助。 – Mars 2014-10-19 02:27:55