繁体   English   中英

什么时候通过nREPL重新加载名称空间不够,整个服务器进程(甚至REPL)都需要重新启动?

[英]When is reloading a namespace via nREPL not enough and whole server process (or even the REPL) needs to be restarted?

我使用nREPL和Emacs的Cider模式玩了一些之后,发现有时我不得不重新启动http-kit服务器以使其接受更改(通常是在更改中间件或路由时),混乱,我只需要重新启动整个REPL。

我很难找出实际上是什么原因造成的。 似乎有时我什至可以更改诸如路由定义(使用compojure defroutes宏定义)之类的东西,并且运行中的服务器会接管事情,有时它不起作用,并且我必须停止服务器并重新启动它。

Clojure中是否有任何特定的模式可以使重新加载更加容易? 还是无法迫使整个REPL重新加载的事情? 我还发现有时我会评估一些东西,例如混乱的导入,这迫使我重新启动整个REPL。

是否有任何最佳实践可服务器运行时 使代码轻松地重新加载 (例如通过Cider中的Cc Ck,以便自动获取更改 我想我很久以前就已经看到过一些东西,可以通过添加一个间接层来使最愚蠢的Web服务器重新加载东西,但是我似乎并没有真正找到它的所在。

以我的经验,REPL中两个最常见的陈旧代码来源是高阶函数和AOT编译。

高阶函数

当您使用诸如comppartial类的高阶函数时,该函数将某个函数作为输入来实现一些应用程序逻辑并返回一个调用该函数的新函数,那么将捕获调用HOF时函数的定义。 输入函数定义的后续更改不会反映在输出函数中。

user=> (defn a [x y] (+ x y))
user=> (def b (partial a 2))
user=> (defn c [y] (a 2 y))
user=> (b 3)
5
user=> (c 3)
5
user=> (defn a [x y] (* x y))
user=> (b 3)
5
user=> (c 3)
6

在上面的例子中,如果a在命名空间中定义foob是命名空间中定义bar ,然后重装foo不会改变的行为b除非你也重新加载bar 如该示例中所建议,如果定义更改,则在调用代码中按名称调用该函数将导致调用新定义。

这与Web开发有关,因为Clojure Web开发的许多基础结构都集中在高阶功能上(即,中间件实质上是功能组成)。 您应该根据自己的判断来决定在习惯上使用高阶函数和在开发过程中轻松重新加载代码之间的适当平衡。

AOT编译

一些Clojure功能(即deftypedefrecorddefprotocol )会导致生成Java类和接口,然后在Clojure代码中的其他地方以它们的Java类名对其进行引用。 当您对该代码进行AOT编译时,将为这些Java类发出.class文件,这些文件随后出现在REPL类路径上。 加载Java类时,总是优先选择.class文件中的定义,而不是动态生成的类定义。 通过这些机制之一重载用于定义Java类的名称空间不会产生任何效果。 您必须重新启动REPL。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM