2024 Clojure 状态调查中分享您的看法!

欢迎!请查看关于页面以获取更多关于如何使用本网站的信息。

0
REPL

嗨!
我正在使用 clojure+nrepl 开发一个扩展插件。
项目的 gradle 依赖关系

dependencies {
    implementation("org.clojure:clojure:1.10.0")
    implementation("nrepl:nrepl:1.0.0")
}

当调用时我得到了 FileNotFoundException

RT.var("clojure.core", varName)

错误在哪里?
谢谢!

1 个答案

+1

被选择
 
最佳答案

RT 是一个内部实现类。

Clojure 的 Java API 地址为 https://clojure.github.io/clojure/javadoc/clojure/java/api/package-summary.html

感谢您的帮助。
我已阅读 Clojure 的 Java API。当我调用
Clojure.var("clojure.core", "+");
时它抛出相同的异常。
通过Thread.currentThread().setContextClassLoader() 解决了这个问题。
大概 idea 插件的运行环境有点特殊。
再次感谢
嗨,alexmiller。
我应该如何使用 Java API 创建一个 nrepl 客户端呢?
我不太会把 Clojure 代码转换为 Java 代码,比如

=> (use '[nrepl.core :as nrepl])
nil
=> (with-open [conn (nrepl/connect :port 59258)]
     (-> (nrepl/client conn 1000)
         (nrepl/message {:op "eval" :code "(time (reduce + (range 1e6)))"})
         doall      pendente `message` 和 `client-session` 都返回惰性序列,因此需要这样的转换
         pprint))
对于任何 Clojure 变量,您将使用 Clojure.var() 来获取其引用,然后调用它。对于像消息这样的字面量,您可以使用 Clojure.read() 从字符串中读取 Clojure 数据,或者使用构造函数,如 hash-map。with-open 是一个宏,但在这种情况下,它基本上是重复了您可以使用 try-with-resources 在 Java 中做的事情,所以您实际上不需要它。-> 需要展开,或者您可以将更多内容放入 Clojure 函数中并直接调用它。

我没有编译这个示例代码,但您最终会得到类似以下的代码

```

private static final IFn require = Clojure.var("clojure.core", "require");
private static final IFn doall = Clojure.var("clojure.core", "doall");

private static final Object portKW = Clojure.read(":port");
private static final Object opKW = Clojure.read(":op");
private static final Object codeKW = Clojure.read(":code");

private static final IFn connect;
private static final IFn client;
private static final IFn message;

static {
  require.invoke(Clojure.read("nrepl.core"));
  connect = Clojure.var("nrepl.core", "connect");
  client = Clojure.var("nrepl.core", "client");
  message = Clojure.var("nrepl.core", "message");
}

public Object getConnection(int port) {
   return connect.invoke(portKW, port);
}

public Object getClient(Object conn, int timeout) {
  return client.invoke(conn, timeout);
}

public Object send(Object client, Object message) {
  Object result = message.invoke(client, message);
  return doall.invoke(result);
}
```

然后


```
try (Object conn = getConnection(59258)) {
  Object client = getClient(conn, 1000);
  Object result = send(client, Map.of(opKW, "eval", codeKW, "(time (reduce + (range 1e6)))"));
  // 这里 result 是一个 map,做你想做的事情
}
```

编辑
谢谢,它连接成功了,有一些小修改

public static IPersistentMap evalCodeMap() {
        Map<Object, Object> map = Maps.newHashMap();
        map.put(Clojure.read(":op"), Clojure.read("eval"));
        map.put(Clojure.read(":code"), Clojure.var("clojure.core", "eval").invoke("(+ 1 2)"));
        return PersistentHashMap.create(map);
    }

Clojure.var("nrepl.core", "message").invoke(client , evalCodeMap())

顺便说一句,Clojure代码看起来更简单。
是直接用Clojure编写代码更好,还是从Java调用Clojure更好?怎么做到?使用gen-class还是require命名空间?
...