从java调用Clojure时Clojure状态的作用域
我是Clojure的新手,所以这可能是一个非常明显的问题,但我找不到任何有用的答案 我正在用Spring Boot实现一个REST服务,它使用Clojure通过多次调用Compiler.eval()来计算结果。我有一些Clojure的东西,应该在所有请求(常量、函数、全局变量等)之间共享,还有一些每个请求的东西,应该对每个请求进行隔离和唯一 我将此服务作为可执行JAR运行,并在类路径中使用clojure.JAR。然而,从JVM的角度来看,您只能通过静态方法访问Clojure,这意味着每个JVM只有一个“Clojure实例”。这意味着,如果您在一个请求期间进行eval(def a 1),那么其他请求也会看到“a” 问题1:我应该在哪里以及如何在Clojure中定义动态(请求范围)变量/符号从java调用Clojure时Clojure状态的作用域,clojure,Clojure,我是Clojure的新手,所以这可能是一个非常明显的问题,但我找不到任何有用的答案 我正在用Spring Boot实现一个REST服务,它使用Clojure通过多次调用Compiler.eval()来计算结果。我有一些Clojure的东西,应该在所有请求(常量、函数、全局变量等)之间共享,还有一些每个请求的东西,应该对每个请求进行隔离和唯一 我将此服务作为可执行JAR运行,并在类路径中使用clojure.JAR。然而,从JVM的角度来看,您只能通过静态方法访问Clojure,这意味着每个JVM只
问题2:假设我希望每个请求都有一个完全“新”的Clojure实例。我怎样才能做到这一点?例如,我可以在同一个JVM中使用相同名称和相同名称空间的变量,但是使用不同的值?我知道我可以通过使用新的类加载器来加载一组全新的Clojure类,但这似乎非常麻烦。在Clojure中不应该使用全局变量,除非需要跟踪某些全局“状态”,而这些状态必须在所有函数之间共享。它是一种函数式语言(嗯,主要是函数式语言),处理事情的函数式方式是将所有必需的东西作为参数传递。这就是如何获得引用透明性,以及如何避免函数看到和影响彼此的值 我不知道您为什么要使用SpringBoot来实现这一点,但也许您可以看看Clojure原生web库是如何工作的。它们通常将某种“请求上下文”传递给处理程序,所有必要的信息都存储在处理程序中 例如,或 因此,回答你的(1):在每个请求中传递它们。 和(2):如果您在每个请求中传递新的值,则不需要这样做。尽管在Clojure中使用一个请求的本地全局变量(请原谅这个丑陋的表达式)并不是一般推荐的web服务方式,但假设您对此有一个有效的用例。一个这样的用例可以是构建一个类似REPL的在线应用程序 隔离请求的一种可能性是为每个请求创建一个临时(随机)名称空间,并在每个请求之后擦除名称空间。用于
sandbox
ing(来自src/trycoljure/models/eval.clj
的片段):
至于1)我会使用
调用并传递每个请求的状态,这不仅仅与web请求相关。假设一个Java程序想要运行多个独立的Clojure程序。我希望能够执行新的Clojure().compiler().load(…)。但由于所有方法都是静态的,所以您实际上无法将一个程序与另一个程序分开,除非您使用单独的类加载器,或者在各自的JVM中启动每个类加载器。因此,尽管它是一种函数式语言,但它本质上充满了静态。这是一个设计缺陷。
(defn make-sandbox []
(sandbox try-clojure-tester
:timeout 2000
:init '(do (require '[clojure.repl :refer [doc source]])
(future (Thread/sleep 600000)
(-> *ns* .getName remove-ns)))))