java 执行clojure脚本_如何从Java调用Clojure宏?

反正有从Java调用Clojure宏吗?

这是我想做的事情:

RT.var("clojure.core","require").invoke(Symbol.create("clojure.contrib.prxml"));

Var prxml = RT.var("clojure.contrib.prxml","prxml");

Var withOutStr = RT.var("clojure.core","with-out-str");

String stringXML = (String) withOutStr.invoke((prxml.invoke("[:Name "Bob"]")));

prxml默认情况下会写入* out *,这就是为什么我需要使用with-out-str宏来包装它,该宏返回字符串。

我收到此错误:

[java] java.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$with-out-str

[java]     at clojure.lang.AFn.throwArity(AFn.java:437)

[java]     at clojure.lang.RestFn.invoke(RestFn.java:412)

[java]     at clojure.lang.Var.invoke(Var.java:365)

[java]     at JavaClojure.xml.main(Unknown Source)

您甚至可以从Java调用宏吗? 我对Clojure不太了解,但是在Lisp中,宏是在编译代码之前由读者评估的。 如果Clojure是相同的方式,那么从Java调用可能为时已晚。 何时在Clojure中扩展宏?

是的,您可以从Java调用Clojure宏,但是您需要调用Clojure阅读器(以便调用编译器并扩展该宏),而不是特定的函数(因为已经编译了函数!)。 可能值得检查这个问题的答案:stackoverflow.com/questions/2181774/calling-clojure-from-java

mikera,我想您会做某事。 我想知道是否有一种好的方法可以在Java宏中调用clojure阅读器。

您必须使用withOutStr滚动。

class YourClass {

static final Var withBindings = RT.var("clojure.core","with-bindings*");

static final Var list = RT.var("clojure.core","list*");

static final Var out = RT.var("clojure.core","*out*");

static final Var prxml = RT.var("clojure.contrib.prxml","prxml");

static String withOutStr(IFn f, Object args...) {

StringWriter wtr = new StringWriter();

withBindings.applyTo(list.invoke(RT.map(out, wtr), f, args));

return wtr.toString();

}

...

String stringXML = withOutStr(prxml,"[:Name "Bob"]");

}

问题是基本的。

invoke(及其姐妹,apply)用于函数。

宏不是函数,因此无法调用它们。宏需要编译。在正常的Lisps中,它们可以被评估或宏扩展或其他任何形式。而且在10m的环顾中,显然Clojure没有简单的RT.eval(String script)函数来简化此过程。

但是,这就是需要做的。您需要编译并执行此操作。

我看到了一个将Clojure与Java JSR 223集成在一起的软件包,并且IT具有评估功能(因为223具有评估功能)。但是我不知道a)包装是否良好或b)这是您要走的方向。

我发现可以使用以下代码获取Java中的Clojure阅读器和评估器:RT.var(" clojure.core"," eval")。invoke(RT.var(" clojure.core"," read-string") .invoke("此处为字符串)。)

很好啊。 是的,我很惊讶我无法在RT之外找到类似的呼叫,但这正是您想要做的。

免责声明:我对clojure知之甚少(我的经验是使用其他功能语言和Java)

但是我的直觉说问题出在prxml.invoke()附近。这里的想法是该语句评估过早,并将结果发送到withOutStr(而不是让withOutStr对其进行评估)。

单独查看在线资源...尤其是RT,Var和AFn以及不带str的clojure文档,我会尝试以下方法:

String stringXML = (String) withOutStr.invoke(RT.list(prxml,"[:Name "Bob"]"));

编辑:另外,我会怀疑它能够从Java调用clojure宏,否则Var上的isMacro()函数似乎很愚蠢...

编辑2:下载了clojure,并尝试了它……不起作用,因此暂时忽略它。

编辑3:with-out-str显然需要2个参数,因此:

final Cons consXML = (Cons) withOutStr.invoke(prxml, RT.list("[:Name "Bob"]"));

final Object[] objs = RT.seqToArray(consXML);

System.out.println(Arrays.toString(objs));

输出为:[clojure.core/let, [s__4095__auto__ (new java.io.StringWriter)], (clojure.core/binding [clojure.core/*out* s__4095__auto__] (clojure.core/str s__4095__auto__))]

我想知道这是否会对有用的东西有所帮助(不确定我对绑定的理解是否正确,必须弄清楚如何通过Java评估缺点。

编辑4:遍历编译器和更多代码,似乎宏实际上有2个隐藏参数。参见提交17a8c90

在编译器中复制该方法:

final ISeq form = RT.cons(withOutStr, RT.cons(prxml, RT.cons("[:Name "Bob"]", null)));

final Cons consXML = (Cons) withOutStr.applyTo(RT.cons(form, RT.cons(null, form.next())));

System.out.println(consXML.toString());

// Output: (clojure.core/let [s__4095__auto__ (new java.io.StringWriter)] (clojure.core/binding [clojure.core/*out* s__4095__auto__] #'clojure.contrib.prxml/prxml"[:Name "Bob"]" (clojure.core/str s__4095__auto__)))

这似乎更有希望,但是它仍然需要评估let表达式,该表达式在编译器中似乎有特殊情况。

如果要从C#或Java执行Clojure代码,请使用Clojure的load-string函数。这将采用一个普通字符串,并完全按照在REPL中键入该字符串的方式执行它。这包括处理宏。

这是C#代码的简短版本。 Java版本离这并不遥远。

private static readonly IFn LOAD_STRING = Clojure.var("clojure.core","load-string");

private void executeButton_Click(object sender, EventArgs e)

{

try

{

object result = LOAD_STRING.invoke(sourceTextBox.Text);

if (null == result)

resultTextBox.Text ="null";

else

resultTextBox.Text = result.ToString() +" (" + result.GetType().Name +")";

}

catch (Exception ex)

{

resultTextBox.Text = ex.ToString();

}

}

您可以在此处查看示例程序的完整版本。它包含许多示例代码来演示Clojure互操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值