2010-03-06 130 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

相关问题