2024年Clojure状态调查!中分享您的想法。

欢迎!请参阅关于页面以了解有关此信息的更多信息。

0
编译器

clojure.lang.Compiler有一个名为

public static Object eval(Object form, boolean freshLoader)

的方法,但由于https://github.com/clojure/clojure/commit/2c2ed386ed0f6f875342721bdaace908e298c7f3,freshLoader参数被忽略

是否有很好的理由还需要像这样“热修复”?

我们想要为eval提供自己的ClassLoader来管理生成类的生命周期。

4 个回答

0

评论作者:stu

这并非Clojure的公共API的一部分。我们需要了解更多有关用例的信息。

0

评论作者:sfnelson

不好意思,Stuart,我们刚刚注意到您的回复,感谢http://ashtonkemerling.com/blog/2016/06/11/my-increasing-frustration-with-clojure/的公开。

我将尽量解释我们的用例,以便您了解情况,但请理解,这个问题只是一个关于一个看起来和闻起来都像公共API函数(谁知道'eval'会是私有的呢)的函数似乎不一致行为的问题。

我们公司使用Clojure语言构建了一个云平台,该平台根据用户请求在从数据库中加载的模块中进行计算。模块是可信代码,但它们独立于我们的平台,因此可能会有多个相同模块版本同时运行(我们希望避免命名空间冲突)。我们已经研究了多种方法,包括使用在单独JVM中运行的容器和微服务来防止模块之间相互干扰,但为了满足简单查询“这个输入是否有效?”的响应时间要求,我们希望在同一个JVM中运行简单查询。

我们用于响应用户查询的一般方法是构建一个用于计算命名空间(可能需要从计算模块加载其他命名空间),然后在已构建的环境中评估表达式。我们有一个LRU缓存来存储模块命名空间,但我们最终还是会有大量的元空间翻滚,我们通过使用Clojure解释器来处理简单查询(评估太慢)来减轻这种情况。

当我们实现我们的LRU模块命名空间缓存时,我们想要尝试在各自的类加载器中加载模块命名空间,以帮助跟踪类生命周期和GC,并希望允许多个命名空间版本共存。但后来我们得出结论,这是不切实际的,因为Clojure与命名空间相关的全局查找如此之多,因此现在我们预处理模块命名空间,在加载时进行名称摇须,并在缓存到期时显式注销已加载的命名空间,以便其类可以被收集。我们避免在模块中使用像多态方法和协议这样的语言特性,这些特性在模块中使用全局变量。

我们并不是在寻求Clojure团队为我们实现容器(尽管这当然是一个很好的功能),这只是我们在API和实现之间注意到的一个不一致性。Java-Interop eval的预期入口点是什么?

0

由:alexmiller 发表评论

您可以使用在 http://clojure.github.io/clojure/javadoc/clojure/java/api/Clojure.html 中记录的Clojure Java API。

导入和使用Clojure Java API的基本示例如下

`
import clojure.java.api.Clojure;
import clojure.lang.IFn;

// ...

IFn read = Clojure.var("clojure.core", "read-string");
IFn eval = Clojure.var("clojure.core", "eval");

Object code = read.invoke("(+ 1 1)");
Object result = eval.invoke(code);
System.out.println("read: " + code + ", eval: " + result);
`

但是,您也可以做一些更复杂的事情,例如生成一个命名空间字符串,并通过相同的方式调用 {{load-string}}。

0
参考:https://clojure.atlassian.net/browse/CLJ-1463 (年由 alex+import 报告)
...