高效的Clojure工作流程?

28

我正在使用Clojure开发一个宠物项目,但想知道如何加快工作流程。

我目前的工作流程(使用Compojure)如下:

  1. 使用lein swank启动Swank。
  2. 转到Emacs,并使用M-x slime-connect连接。
  3. 逐个加载所有现有源文件。这也会启动Jetty服务器和应用程序。
  4. 在REPL中编写一些代码。
  5. 当实验满意时,编写我打算构建的结构的完整版本。对其进行评估(C-c C-c)。
  6. 将REPL切换到这个构造所在的命名空间并进行测试。
  7. 切换到浏览器并重新加载受影响的页面选项卡。
  8. 修改代码,评估它,在浏览器中检查。
  9. 重复上述任何步骤。

以下是其中一些问题:

  1. 我必须不断在Emacs和浏览器之间切换(如果我正在测试像多个浏览器之类的东西以获得模板),有没有常见的惯用语来自动化这个过程?我曾经有一小段JavaScript代码可以持续地重新加载页面,但显然当我需要与页面交互超过几秒钟时,它的效用就有限了。
  2. 当我试验和编写测试函数时,我的JVM实例变得“脏”。基本上,命名空间被污染了,特别是当我在不同的命名空间之间重构并移动函数时。这可能导致符号冲突,因此我需要重新启动Swank。我能否取消定义一个符号?
  3. 我会在重新启动Swank时逐个加载所有源文件(C-c C-k)。我怀疑我做错了什么。
  4. 在REPL和文件编辑器之间切换有点烦人,尤其是当我有很多Emacs选项卡打开时,以及浏览器。

我正在寻找改进上述问题和整个工作流程的办法,所以如果您能分享您的方法,我将不胜感激。

P.S.:

我以前也使用过Vimclojure,所以欢迎基于Vimclojure的工作流程。

2个回答

19

以下是一些想法,而不是完整的工作流程描述:

  1. 可以使用 ns-unmap 函数从命名空间中移除变量。为了方便起见,可以在其上构建一个 undef 宏,例如:

(defmacro undef [& syms]
  `(do ~@(map (fn [s] `(ns-unmap *ns* '~s)) syms)))

ns-unalias 也许会对你有用。

  • 没有必要通过访问包含命名空间的文件来执行每个文件中的 C-c C-k 命令;你可以在 REPL 中使用 require 导入��需要的命名空间。

    此外,如果你在 SLIME REPL 中输入一些字符然后使用 M-p / M-n 浏览历史记录,只有与你手动输入的文本匹配的条目才会显示。这与 Paredit 兼容(结尾的闭合括号不会成为问题)。因此,如果你在开始时构建了一个庞大的 require -- (require '[foo :as f] '[bar :as b] '[clojure.contrib.sql :as sql] …) -- 那么在重新启动 Swank 后,你只需键入类似于 (require '[f 并按下 M-p 即可将该表单再次带回 REPL 提示符。

    不可否认,这可以通过多种方式自动化(例如,让 Swank REPL 搜索配置文件,或者可能是一个简单的宏展开为适当的 require 表单,可以在从项目中仅引入一个实用程序命名空间后使用 -- 尤其是后一种想法很容易实现),但我认为其烦恼因素足够低,以至于我到目前为止还没有费心改进。

  • 你可以使用 C-c C-z 在 SLIME 启用的缓冲区中弹出 SLIME REPL 窗口。此外,如果你尚未尝试过,应该使用 ido。我倾向于在屏幕左侧的窗口中打开代码缓冲区,右侧是 REPL 缓冲区;将 windmove-leftwindmove-right 绑定到一些方便的按键上,我通常会很高兴。如果我经常需要查看其他缓冲区,则使用额外的 Emacs 帧。

  • 顺带一提,我通常不使用 lein swank,我更喜欢我的自定义 clojure-project 函数(Phil Hagelberg 的原始版本的调整版)。偶尔,我想改进它...也许下次我会处理每个项目的import / require 自动化。;-)


  • 5

    我不确定Lein,但在Maven中,您可以指定repl脚本的名称(replScript配置参数),这允许指定在启动REPL和Swank时将执行哪些命令...如果您的项目有单独的命名空间,您可以使用clojure.contrib.find-namespaces函数查找您的命名空间并将它们全部加载....


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接