Comment made by: sfnelson
抱歉,Stuart,我们刚刚注意到您的回复,感谢 http://ashtonkemerling.com/blog/2016/06/11/my-increasing-frustration-with-clojure/ 的宣传。
我将尝试解释我们的用例,以便提供一些背景信息,但请理解,这个问题仅仅是一个关于看起来像是公共 API 函数(谁知道 'eval' 会是私有的 :-)的不一致行为的问题。
我们公司使用Clojure来构建一个云计算平台,该平台根据用户请求在数据库中装载数模块执行计算。模块是受信任的代码,但它们与我们的主平台是独立的,因此同一时间可能会运行相同模块的多个版本(我们想避免命名空间冲突)。我们已经研究了多种方法来防止模块相互干扰,包括运行在分离JVM中的容器和微服务,但为了保证简单的查询,例如“这个输入是否有效?”的可接受响应时间,我们希望在运行在Web服务器同一个JVM上执行简单查询。
我们回答用户查询的一般方法是为我们的计算创建一个命名空间(这可能需要从计算模块加载其他命名空间),然后在构建的上下文中评估表达式。我们有模块命名空间的LRU缓存,但评估过程中仍然产生了大量元空间的碎片,我们通过使用clojure解释器来处理简单查询(eval速度过慢)来缓解这一问题。
在实现我们自己的LRU模块命名空间缓存时,我们想要尝试将模块命名空间装入它们自己的类加载器中,以帮助跟踪类生命周期和GC,并希望能够使多个命名空间版本共存。但我们发现这并不实际,因为Clojure中有许多与命名空间相关的全局查找,因此我们现在在加载时对模块命名空间进行预处理,并对名称进行混编,在缓存到期时明确注销加载的命名空间,以便收集它们的类。我们避免在模块中使用像multimethods和protocols那样使用全局的编程语言功能。
我们并不是要求Clojure团队为我们实现容器(虽然这当然是一个很好的功能!),这仅仅是我们注意到API和实现之间不一致性。Java-interop eval的预期入口点是什么?