【发布时间】:2018-10-01 06:13:57
【问题描述】:
我们几乎可以立即在运行时重新加载 Clojure 中的任何函数和/或变量。我们甚至可以更改方法签名。对于 Scala 或 Java,我们能做的最多就是使用速度慢、商业化和受限的 JRebel。让 Clojure 具有如此交互性的区别是什么? 在 Slack 中阅读此内容时,我发现了以下 cmets,但我希望了解更多相关信息。还感谢您提供进一步阐明该问题的论文/文章的链接(尽管不是必需的)。
这主要是因为语言设置为可重新加载。 Clojure 对每个函数或顶级变量都有一个 var 间接寻址 你可以改变的定义,所以你可以只重新定义一个函数 同时保持环境的其余部分不变并继续进行
.
跟进 - 当函数名称为 在代码中,但是对于需要另一个长时间运行的函数 作为参数的函数(例如,您将处理函数传递给 http 服务器进程启动)您可以通过以下方式获得 var 间接的好处 手 - 通过传递 #'handler 而不是处理程序,否则你不 重新加载(不重新启动使用该 arg 的进程)
.
一种
直接链接将正在编译的 var 调用替换为直接调用 (已编辑)但是 var 路径仍然存在,并且新代码仍然可以 通过变量调用
【问题讨论】:
-
看起来您在您发布的报价中找到了问题的答案。大多数 Lisp 允许这种编辑 AFAIK。您可能还想看看 smalltalk。
-
@nha 我觉得我不太了解 cmets。什么是 var 间接?为什么其他语言不直接复制这个想法?有哪些取舍?为什么#'handler 与handler 不同?可以在用户代码中重新定义已编译的方法(例如来自核心库的方法)吗?是否存在安全问题?什么是 var 路径? ...
-
请阅读 clojure.org/reference/vars swannodette.github.io/2014/12/17/whats-in-a-var blog.cognitect.com/blog/2016/9/15/… 可能还有其他内容,但这些内容应该能让您很好地理解什么是 var。
-
JVM 在字节码级别不再支持不同语言的热交换。但是,如果语言级别更高,它可以在语言级别进行更改,这看起来不像在字节码级别上不受支持的更改。
-
还因为考虑到 clojure 的语义,您要重新加载的是通常是纯函数。这通常不是真的,例如Java,因为在 Java 中您将重新加载类文件,这可能会破坏您当前重新加载的类实例的结构。
标签: clojure jvm read-eval-print-loop jrebel hotswap