2010-03-06 133 views
46

我是Clojure的新手,開始嘗試構建應用程序。到目前爲止,我所見過的所有關於編譯Clojure程序的教程都涉及到交互性。例如,「加載REPL並輸入(加載文件」this-that-that「)即可運行。這很好,但這還不夠。構建和部署Clojure應用程序的最佳實踐:好的教程?

我很習慣編輯編譯運行的習語的C語言或德爾福語言,我本能地驅動編輯,然後打「Mx編譯」

問題是,「lein uberjar」,我理解是相當於「make」,是痛苦地慢甚至是爲了一個hello世界而執行,所以我必須弄清楚這個「互動開發」的東西是如何工作的,停止使用像快速製作的uberjar,並且只在一天結束時才保存。

我在建立時使用lein uberjar的另一件事是,s購物中心GUI應用程序我正在編譯過程中彈出框架,就好像它們在編譯時執行時一樣。這對我來說似乎有點違反直覺;它不像我想象的那樣與「製造」很相似。

我知道開發事物的Lisp方式是在REPL中交互式工作的,我不想改變:我想適應這種生活方式。不幸的是,我沒有看到如何做文件的形式。例如,如何重置機器的當前狀態。只是在不能進行某種重置的情況下繼續編譯單個片段似乎很麻煩。

我在Clojure(和Lisp)上看到的大多數教程似乎都將重點放在了對REPL的黑客攻擊上。部署應用程序的最佳實踐對我來說仍然是一個謎。我的用戶只是成爲用戶;他們不會成爲將文件加載到REPL的開發人員。

所以,這裏是我的問題:任何資源的良好信息或教程建立一個Clojure應用程序的整個過程,包括部署? (注意:我已經安裝並運行了所有的必備軟件(例如Emacs,Slime,Leiningen等),所以這不是一個問題)。

回答

25

一對夫婦快速提示,然後一些鏈接:

不要開發過程中使用lein uberjar;寧願lein jar。區別在於lein uberjar將所有的依賴關係放入生成的jar(包括Clojure本身)中,這樣,您的單個jar就是一個完全獨立的包,其中包含您的應用程序; lein jar只能打你自己的代碼。 uberjar方法對於部署有顯而易見的好處,但對於開發,您應該能夠在運行應用程序時僅使用適當的類路徑,從而節省準備uberjar所需的時間。如果您不想爲測試運行手動管理類路徑,請查看lein run plugin

另外,很可能大部分代碼實際上不應該被AOT編譯。 AOT在某些Java互操作場景中是必需的,但大多數情況下,它會使啓動速度略有提升,並且會對Clojure不同版本的二進制兼容性產生惱人的問題。我認爲後一個問題與獨立應用類型的項目無關,但任何庫代碼至少應該儘可能地進行JIT編輯。使用Leiningen,您可以在project.cljdefproject表格中輸入:namespaces子句,以確定要編譯哪些名稱空間;無論你遺漏了什麼,目前默認情況下都會進行JIT編輯。老版本的Leiningen用於默認編譯所有內容,這實際上是升級的一個很好的理由!

至於在編譯期間彈出的窗口,我猜想你要麼在宏展開時或在任何函數定義或類似結構之外運行窗口跳出代碼。 (就像頂級的(println "Foo!"))。我想這只是你不應該做的 - 除非你打算把你的代碼作爲腳本來運行。爲避免此問題,請在函數定義中包裝副作用代碼,並使用project.clj中的:main子句爲應用程序提供入口點。 (如果你說:main foo,那麼foo命名空間中的-main函數將作爲你的應用的入口點。這是默認的,至少上面提到的lein run似乎有硬編碼的名字 - 不確定關於lein本身)。

至於重置REPL的狀態 - 你可以重新啓動它。使用SLIME,M-x slime-restart-inferior-lisp將在保持Emacs會話的所有其他狀態的同時執行此操作。

又見Clojure的谷歌組這些討論:

  1. Clojure for system administration
  2. Prepping clojure for packaging (was: Re: Clojure for system administration)
  3. Leiningen, Clojure and libraries: what am I missing?
+0

感謝您的信息和鏈接! lein運行插件看起來會幫助我。當然,這導致了另一個問題:http://stackoverflow.com/questions/2393705/how-to-install-a-leiningen-plugin – kes 2010-03-06 18:54:43

+0

不客氣!剛剛回答了這個新問題。 :-) – 2010-03-06 19:01:41

13

不,你不要在REPL輸入功能。

像往常一樣編輯源文件。 Lisp的優勢在於您可以同時在後臺運行系統,因此您可以從源文件編譯單個函數並將它們放入正在運行的系統中,甚至可以在那裏替換它們。

如果你使用Slime,你可以在源文件中按C-c C-c來編譯和加載函數。然後,您可以切換到REPL以進行測試和探索,但是您想將其作爲源保存的任何內容放入源文件中。

教程通常從在REPL上輸入內容開始,因爲您不需要爲此設置太多內容,但嚴重的開發集成了正在運行的系統和源文件管理。


只是爲了說明這一點,我平時的工作流程(我用的Common Lisp,但Clojure是相似的)是這樣的:

  • 啓動Emacs
  • M-x slime開始煤泥,Lisp的系統,並通過Swank連接兩個
  • ,(命令)load-systemfoo將當前項目(僅在必要時編譯)載入圖像
  • C-x b切換到源緩衝區
  • C-c ~使源目錄中的當前目錄和源碼包當前包的REPL

現在,我成立了我的系統在後臺運行。工作則是:

  • 改變或增加一個功能或類定義
  • C-c C-c編譯和其加載到圖像
  • 開關REPL,測試
  • 調試

有沒有重要的編輯暫停,因爲我從不編譯整個事情,只是個別的定義。

+2

還有'C-C C-z'用於從任何Lisp源緩衝區切換到REPL緩衝區。一般來說,學會充分利用SLIME和Paredit是最重要的優先事項 - 然後有一些不那麼重要但仍然非常有用的東西,例如, ido模式(或者是實現類似目的的東西 - 可能是冰柱或任何東西)。 (感謝編輯,順便說一下!) – 2010-03-06 16:18:59

+0

我在'C-c s'設置了粘液選擇器,它提供了更多的緩衝切換選項。 – Svante 2010-03-06 18:24:58

相關問題