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

by
感谢您的帮助。
我已经阅读了Clojure的Java API。当我调用
Clojure.var("clojure.core", "+");
时,抛出了相同的异常。
通过
Thread.currentThread().setContextClassLoader();
解决了问题,可能IntelliJ插件的环境很特殊。
再次感谢
by
Hi, alexmiller。
我该如何使用Java API为Clojure创建一个nrepl客户端?

我不能将Clojure转换成Java,例如
=> (require '[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      ;; `message` and `client-session` all return lazy seqs
         pprint))
by

对于任何Clojure var,您将使用Clojure.var()来获取其对引用,然后在其上调用invoke()。对于像消息这样的文字,您可以既要使用Clojure.read()从字符串中读取Clojure数据,也可以使用构造函数像hash-map。with-open是宏,但在此情况下,它基本上是在Java中try-with-resources可以做的同样的操作,因此您实际上不需要它。->在这里需要展开,或者您可以将更多内容放入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) {
}

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命名空间?
...