首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在REPL中重新加载clojure文件

如何在REPL中重新加载clojure文件
EN

Stack Overflow用户
提问于 2011-10-05 17:09:48
回答 8查看 71.6K关注 0票数 182

重新加载Clojure文件中定义的函数而不必重新启动REPL的首选方法是什么。现在,为了使用更新后的文件,我必须:

打开REPL

  • (load-file "src/foo/bar.clj")

  • (use 'foo.bar)

,然后编辑src/foo/bar.clj

  • close

此外,(use 'foo.bar :reload-all)不会产生所需的效果,即计算修改后的函数体并返回新值,而不是表现为源代码根本没有更改。

Documentation:

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2013-12-03 05:12:27

(use 'your.namespace :reload)

票数 215
EN

Stack Overflow用户

发布于 2013-04-12 20:50:35

还有一种替代方案,比如使用tools.namespace,它非常高效:

代码语言:javascript
复制
user=> (use '[clojure.tools.namespace.repl :only (refresh)])

user=> (refresh)

:reloading (namespace.app)

:ok
票数 80
EN

Stack Overflow用户

发布于 2014-09-23 01:16:55

使用(require … :reload):reload-all重载Clojure代码是very problematic

  • 如果修改两个相互依赖的命名空间,则必须记住以正确的顺序重新加载它们,以避免编译错误。
  • 如果从源文件中删除定义,然后重新加载它,则这些定义在内存中仍然可用。
  • 如果重新加载的命名空间包含defmulti,您还必须重新加载所有关联的defmethod expressions.
  • If重新加载的命名空间包含defprotocol,您还必须重新加载实现该协议的任何记录或类型,并用新的instances.
  • If替换这些记录/类型的任何现有实例。重新加载的命名空间包含宏,还必须重新加载使用这些宏的任何名称空间。
  • 如果正在运行的程序包含关闭重新加载的名称空间中的值的函数,则不会更新这些关闭的值。(这在将“处理程序堆栈”构建为函数组合的web应用程序中很常见。)

clojure.tools.namespace库极大地改善了这种情况。它提供了一个简单的刷新函数,可以根据名称空间的依赖关系图执行智能重新加载。

代码语言:javascript
复制
myapp.web=> (require '[clojure.tools.namespace.repl :refer [refresh]])
nil
myapp.web=> (refresh)
:reloading (myapp.web)
:ok

不幸的是,如果引用refresh函数的名称空间发生更改,则第二次重新加载将失败。这是因为tools.namespace会在加载新代码之前销毁命名空间的当前版本。

代码语言:javascript
复制
myapp.web=> (refresh)

CompilerException java.lang.RuntimeException: Unable to resolve symbol: refresh in this context, compiling:(/private/var/folders/ks/d6qbfg2s6l1bcg6ws_6bq4600000gn/T/form-init819543191440017519.clj:1:1)

您可以使用完全限定的var名称作为解决此问题的方法,但就我个人而言,我不希望在每次刷新时都键入该名称。上面的另一个问题是,在重新加载主名称空间之后,标准的REPL helper函数(如docsource)不再被引用。

为了解决这些问题,我倾向于为用户名称空间创建一个实际的源文件,以便能够可靠地重新加载它。我把源文件放在~/.lein/src/user.clj中,但是你可以放在任何地方。该文件应该需要顶部ns声明中的刷新函数,如下所示:

代码语言:javascript
复制
(ns user
  (:require [clojure.tools.namespace.repl :refer [refresh]]))

您可以在~/.lein/profiles.clj中设置a leiningen user profile,以便将放置文件的位置添加到类路径中。配置文件应如下所示:

代码语言:javascript
复制
{:user {:dependencies [[org.clojure/tools.namespace "0.2.7"]]
        :repl-options { :init-ns user }
        :source-paths ["/Users/me/.lein/src"]}}

请注意,我在启动REPL时将用户名称空间设置为入口点。这确保在用户名称空间中引用REPL助手函数,而不是在应用程序的主名称空间中引用。这样,除非您更改我们刚刚创建的源文件,否则它们不会丢失。

希望这能有所帮助!

票数 69
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7658981

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档