评论人:sfnelson
抱歉Stuart,我们刚刚注意到您的回复,多亏了http://ashtonkemerling.com/blog/2016/06/11/my-increasing-frustration-with-clojure/上的宣传。
我将尝试稍微解释我们的用例以供参考,但请理解,这个问题只是关于一个看起来很像是公共API函数的函数(谁会想到eval是私有的 :-))的不一致行为。
我们公司使用Clojure构建一个云平台,该平台通过从数据库加载的模块响应用户请求进行计算。这些模块是可信任的代码,但它们独立于我们的主平台,因此可能同时运行多个相同模块的版本(我们希望避免命名空间冲突)。我们审视了许多方法以保持模块之间不相互干扰,包括运行在单独JVM上的容器和微服务,但为了确保简单查询(如“这个输入是否有效?”)的可接受响应时间,我们希望在Web服务器相同的JVM中运行简单查询。
我们回答用户查询的一般方法是为我们的计算构建一个命名空间(这可能需要从计算模块加载其他命名空间),然后在构建的上下文中评估表达式。我们有一个LRU缓存用于模块命名空间,但我们最终仍然会因为评估而在元空间产生大量的 churn,我们通过使用Clojure解释器来处理简单查询来缓解这种情况(评估太慢)。
当实现我们的LRU模块命名空间缓存时,我们希望尝试将模块命名空间加载到它们自己的类加载器中,以帮助跟踪类生命周期的GC,并希望允许多个命名空间版本共存。但后来我们得出结论,这是不切实际的,因为Clojure有太多的与命名空间相关的全局查找,所以我们现在在加载时对模块命名空间进行预处理并执行名称变换,当缓存过期时显式注销已加载的命名空间,以便它们的类可以被回收。我们避免在模块中使用使用全局变量的语言功能,如multimethods和protocols。
我们不是在寻找Clojure团队为我们实现容器(尽管那当然是一个非常实用的功能!),这只是在API和实现之间注意到的一种不一致。Java interop eval的预期入口点是什么?