Clojure REPL哲学和实用程序应用

Clojure REPL哲学和实用程序应用,clojure,executable-jar,Clojure,Executable Jar,很抱歉发了这么长的帖子,但是这个论坛总是询问用例:-) 我经常被要求为我的组织编写实用程序(GUI和命令行)。我通常用Java编写这些代码,最近用的是Scala Clojure(和其他Lisp)中的“哲学”似乎以REPL为中心,我不得不承认它提供了一个很好的开发环境,但我显然无法生成需要用户使用的实用程序“安装Clojure和Clojure contrib,然后将该实用程序解压到硬盘上的一个目录中,使用以下类路径从命令行启动Clojure,…”。用户不关心该实用程序是否是用Clojure编写的。

很抱歉发了这么长的帖子,但是这个论坛总是询问用例:-)

我经常被要求为我的组织编写实用程序(GUI和命令行)。我通常用Java编写这些代码,最近用的是Scala

Clojure(和其他Lisp)中的“哲学”似乎以REPL为中心,我不得不承认它提供了一个很好的开发环境,但我显然无法生成需要用户使用的实用程序“安装Clojure和Clojure contrib,然后将该实用程序解压到硬盘上的一个目录中,使用以下类路径从命令行启动Clojure,…”。用户不关心该实用程序是否是用Clojure编写的。他们只需要指向并单击,或者最多在命令行上键入“java-jar utility.jar-?”

我的问题集中在编译和将应用程序分离为许多名称空间/文件上

我知道
main
方法必须在Clojure文件中,该文件包含
(gen class…
命令(或
ns
命令上的
:gen class
子句)。我对附加的Clojure文件也是这样做的,还是应该将它们作为源代码保存在JAR中,并由
main
文件加载?在开发过程中测试REPL中的附加文件如何


我一直在使用leiningen、cake和maven构建自包含的jar(包含未打包的clojure.jar、clojure-contrib.jar和commons-cli.jar文件),但到目前为止,我一直在使用
main
方法在同一个文件中编写代码。

是将.clj编译成.class还是让Clojure在运行时动态编译,这取决于您自己。一般来说,我发现在开发过程中更容易避免AOT,而在编译成本较高的情况下,只需将AOT用作性能提升器即可运行中的ur.clj没有意义(有限的环境,如Google App Engine或实用程序,启动时间非常关键)。对于将运行很长时间的服务器进程,AOT编译没有多少优势

在开发时使用特定于不同开发环境的AOT类有许多复杂性


AOT的一个缺点是,您编译的类可能与Clojure的未来版本不兼容,这比您的clj文件更可能不兼容。随着时间的推移,这可能变得更重要。

说到分离,我会将它们保存在单独的名称空间/文件中:

  • 一个用于
    :gen类
    名称空间,包含
    -main
    和所有其他类似Java的内容
  • 所有函数的另一个命名空间
理想情况下,main应该只包含来自另一个名称空间的函数调用,或者可能包含用于计算或重新打包
args
的一些逻辑

您的问题似乎与逻辑代码和ui代码之间的分离非常相似。您可以将带有
:gen class
的名称空间视为您的程序提供给Java代码的接口,仅此而已


当涉及到实用程序(如命令行或Swing应用程序等)时,由于JVM的启动时间,Java通常存在问题

现在,您可以通过让服务器应用程序始终在后台运行REPL来解决这个问题,并说,以某种方式接收要计算的s-expr,然后返回结果。这可以作为一个简单的web应用程序来完成,该应用程序接收s-expr作为URL参数,然后返回结果。现在,您可以使用普通的旧Java制作所有实用程序,甚至可以使用wget访问bash,因为您所要做的就是访问一个URL(假设带有repl的服务器在后台运行)

这样的事情很有可能已经存在,所以如果有人知道的话,评论是非常受欢迎的


哦,还有一件事,repl webapp暴露的端口可能必须对外界关闭,以防止Clojure注入:D

不能做webapp。我们在全国各地都有服务器——在防火墙之外,我需要在那里以及我们的总部运行实用程序。启动时间从来都不是问题Java应用程序;大多数是数据库实用程序,可以处理大量查询等问题。数据库通常是瓶颈。不过,谢谢你的回答。@Ralph:好的,我添加了一行,将与你的问题相关的上半部分与不适用于你的问题的下半部分分开。