生活在REPL中(续):在REPL中动态加载依赖的库

在以前的文章《生活在REPL中:工具与程序一体》中,我描绘了把Clojure REPL当作SHELL来使用的场景,在REPL中作诸如访问数据库、加解密等平常开发工做。java

但使用REPL中最郁闷的就是依赖的类库没法动态加载。例如代码运行到一半,突然发现须要解析JSON字符串,不得不退出REPL,在project.clj中添加依赖的JSON解析包,而后从新进入REPL并敲一堆代码恢复到以前退出的场景。这一方面Clojure或者说Java没法作到像SHELL那样简便地修改PATH环境变量同样修改CLASSPATH,以实现动态加载类库的目的。shell

今天终于下决心解决这个问题,而且我相信确定已经有解决方案了!网络上搜索了半天,终于在一篇StackOverflow的帖子中看到了相关的解答:使用alembic,可实现动态加载类库的功能。具体方法以下:数据库

  1. project.clj中引入[alembic "0.3.2"]或更高版本
  2. lein repl
  3. (require 'alembic.still)
  4. (alembic.still/distill '[org.clojure/data.codec "0.1.0" :exclusions [org.clojure/clojure]])

其中alembic.still/distill可用兼容project.clj的语法来动态加载依赖的类库,而后就能够在后续的REPL中使用动态加载的类了。网络

找了方法后,为了方便后续的使用,我想修改$HOME/bin/clojure脚本。原来这个脚本是用来运行java clojure.main的:没有参数则进入REPL;不然将参数做为脚本文件名逐个执行。如今我但愿用lein repl代替它,步骤以下:函数

  1. $HOME/.lein/profiles.clj中添加exec-plugin,用于将.clj文件做为脚本执行
    {:user {:plugins [lein-exec "0.3.6"]}}
  2. $HOME/.lein/repl中新建工程(lein new me.zzp/repl),用于执行lein replproject.clj以下
    (defproject me.zzp/repl "1.0.0"
      :description "Global Clojure REPL"
      :dependencies [[org.clojure/clojure "1.8.0"]
                     [alembic "0.3.2"]]
      :main ^:skip-aot me.zzp.repl)
  3. me.zzp.repl中添加一些自定义的函数或宏:
    (ns me.zzp.repl
      (:require alembic.still))
    
    (defmacro dep [& args]
      `(alembic.still/distill '[~@args]))
    
    (defn -main [& args])
  4. 添加$HOME/bin/clojure脚本
    #!/bin/sh
    
    if [ $# -eq 0 ]; then
        cd "$HOME/.lein/repl"
        exec lein repl
    else
        exec lein exec "$@"
    fi
相关文章
相关标签/搜索