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

原创
2016/04/17 00:51
阅读数 606

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

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

今天终于下决心解决这个问题,并且我相信肯定已经有解决方案了!网络上搜索了半天,终于在一篇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
    
展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
2 收藏
1
分享
返回顶部
顶部