如何使用我自己版本的 Clojure 库?
假设我对 Clojure 库进行了更改(例如,向 clj-oauth 中的请求令牌添加了一个参数),并且想要在我的项目中使用更改后的库。除了将新库编译为 JAR 并将其复制到我的项目库之外,最好的方法是什么?
我希望能够同时调整库和我的项目(最好是在 REPL 中)。如果我在 Ruby 中执行此操作,我将下载并“需要”gem,然后在我自己的项目源中重新打开该类,并根据需要添加或重写方法。
Say I made a change to a Clojure library (eg. added a parameter to the request-token in clj-oauth) and want to use that changed library in my project. What's the best way to do this, short of compiling the new library as a JAR and copying that to my project lib?
I want to be able to tweak the library and my project at the same time (preferably in the REPL). If I were doing this in Ruby, I would download and 'require' the gem, then reopen that class in my own project source and add or override the methods as needed.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以直接破解 REPL。假设您的类路径上有 incanter。
开始 REPL。我们需要做的第一件事是将 incanter 类引入其中。
现在我们可以看到函数 incanter.core/matrix?
我们可以看一下原来的源代码:
让我们把它搞砸了:
首先更改为 incanter.core 命名空间:
然后我们可以重新定义它,使用旧的源代码作为婴儿床:
单元测试:
切换回用户命名空间:
尝试一下:
没有用户/矩阵的定义。我们在 incanter.core 命名空间中重新定义了它。
为了在 repl 上进行实验,只需更改源文件并重新编译单个文件(emacs 中的 CC Ck)即可,或者如果您位于正确的命名空间中,只需重新评估定义即可。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
现在,如果我们想让我们有价值的改变永久存在并可供其他项目使用,这取决于一切的设置方式。
我使用 Maven 进行依赖管理,因此需要修改源文件,然后重新运行库的构建过程来编译新版本并将其安装到本地 Maven 存储库中。
对于 Maven 项目,这应该像
关于版本号的注释一样简单:
如果您确实进行了永久性修改并使用依赖项管理来协调差异,那么您应该更改库的版本号,从 1.2.0 更改为 1.2 .0-johnshack-SNAPSHOT,或者当您想在另一个项目中使用未变态的版本时不太可能与真实版本发生冲突的东西。您不希望修改后的版本进入不受欢迎的项目。
然后,您修改自己的项目文件,以确保在您想要的位置使用 hacked 版本,并且下次启动 repl 时,它应该会引入您安装的最后一个 hack。
每次您希望更改进入存储库时,您都需要重新安装,但这实际上可能是一件好事。
不幸的是,(正是在这一点上,我开始希望我选择了一个不同的例子)Incanter 原来是一个 leiningen 项目,它以一种特殊的脚本方式分成子模块,所以我们需要弄清楚它预计如何安装。尽管答案很简单,但找出答案却相当困难。莱宁根点燃了我的头发。
你可以在这里获取 incanter 的源码:
$ git clone http://github.com/liebke/incanter.git
相关源文件为:
~/incanter/modules/incter-core/src/incanter/core.clj
修改它以破坏矩阵?函数,然后事实证明您要做的是:
更改顶级project.clj 和子模块project.clj 中的版本号。
然后,您在 incanter-core 目录中运行 lein install,然后在顶级目录中再次运行 lein install,并且必须按此顺序执行。我不太明白为什么。
目前,这一切似乎没有必要复杂化。我(相当)确信随着工具的成熟,它会稳定下来。
You can hack directly at the REPL. Suppose you've got incanter on your classpath.
Start a REPL. The first thing we need to do is bring the incanter classes into it.
Now we can see the function incanter.core/matrix?
We can look at the original source code:
Let's go and screw it up:
First change to the incanter.core namespace:
Then we can redefine it, using the old source code as a crib:
Unit test:
Switch back to the user namespace:
Try it out:
There is no definition of user/matrix. We redefined it in the incanter.core namespace.
For experimenting at the repl, it's ok just to change source files and re-compile the single file (C-C C-k in emacs), or if you're in the right namespace, just re-evaluate the definition.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Now, if we want to make our valuable change permanent and available to other projects, it depends on how everything is set up.
I use maven for dependency management, so it would be a question of modifying the source file, and then re-running the build process for the library to compile the new version and install it into the local maven repository.
With a maven project, that should be as simple as
A note about version numbers:
If you do make permanent modifications and use dependency management to coordinate the differences, then you should change the version number of your library, from maybe 1.2.0 to 1.2.0-johnshack-SNAPSHOT, or something that is unlikely to collide with the real thing when you want to use an unperverted version in another project. You wouldn't want a modified version finding its way into projects where it isn't welcome.
Then you modify your own project files to make sure that you use the hacked version where you want to, and the next time you start your repl, it should pull in the last hack that you installed.
You will need to reinstall again every time you want your changes to make their way into the repository, but that's actually probably a good thing.
Unfortunately, (and it was at this point that I started to wish that I had chosen a different example) Incanter turns out to be a leiningen project which is split into sub-modules in an ad-hoc scripty sort of way, so we need to figure out how it expects to be installed. The figuring out turned out to be quite hard, although the answer is easy. Leiningen sets my hair on fire.
You can get incanter's source here:
$ git clone http://github.com/liebke/incanter.git
and the relevant source file is:
~/incanter/modules/incanter-core/src/incanter/core.clj
Modify it to break the matrix? function, and then it turns out that what you have to do is:
Change the version numbers in both the top level project.clj, and also in the submodule project.clj.
Then you run lein install in the incanter-core directory, and then again in the top-level directory, and you have to do it in that order. I don't quite understand why.
At the moment all this seems needlessly complicated. I'm (fairly) sure that it will settle down as the tools mature.
如果您正在使用(或不介意使用)cake,请查看子项目依赖项部分自述文件。我想这可能正是您正在寻找的。
If you're using (or wouldn't mind using) cake, check out the subproject dependencies section of the README. I think it might be exactly what you're looking for.
您可以根据不同的名称将其上传到 clojars。
You upload it to clojars under a different name depend on that.