clojure如何通过接口IFn中定义的函数调用来调用clj文件中的方法?

时间:2019-07-05 02:55:57

标签: clojure

我尝试阅读clojure的编译器源代码

我知道主要方法在jvm / clojure / main.java

还有一个具有主要方法的Java文件:jvm / clojure / lang / Compile.java

当我想获取clojure.jar时似乎无法编译clj文件,尽管默认情况下会编译clj文件。我可以删除pom.xml中的“ clojure-compile”部分,得到1.8 M clojure.jar,而不是4.6M clojure.jar。那也可以。我只能编译java文件,没有clj文件。

在main.java中,clojure似乎会创建许多默认的命名空间,变量,符号

然后它将使用IFn.java中定义的调用“调用” .clj文件中定义的某些方法,例如:

in_ns.invoke(USER);
refer.invoke(CLOJURE);
require.invoke(SERVER);
start_servers.invoke(System.getProperties());
REQUIRE.invoke(CLOJURE_MAIN);
MAIN.applyTo(RT.seq(args));

然后爆炸!clojure可以工作,我可以跑步(+1 1)

但是我找不到invoke方法的实现在哪里。它似乎是空的。在Var.java中,接口是这样实现的:

 return fn().invoke(Util.ret1(arg1,arg1=null));

final public IFn fn(){
return (IFn) deref();
}

final public Object deref(){
TBox b = getThreadBinding();
if(b != null)
    return b.val;
return root;
}

线程似乎有这个:

Var.pushThreadBindings(
        RT.mapUniqueKeys(CURRENT_NS, CURRENT_NS.deref(),
               WARN_ON_REFLECTION, WARN_ON_REFLECTION.deref()
                ,RT.UNCHECKED_MATH, RT.UNCHECKED_MATH.deref()));

无论如何,我阅读了源代码的时间,似乎已经创建了许多数据结构,但是我不知道如何调用clj文件中定义的方法,即使我不能编译clj文件,也只能保持它们文本文件

你能教我吗?谢谢!

1 个答案:

答案 0 :(得分:0)

目前尚不清楚您要实现的目标。您是否正在尝试从头开始编译Clojure本身?您是否要了解Clojure编译器的工作原理?

似乎您还没有从正确的课程开始。 clojure.main中的类是Clojure REPL本身,而不是编译器。实际上,您可以从Java启动它:

$ java -cp /home/denis/.m2/repository/org/clojure/clojure/1.10.0/clojure-1.10.0.jar:/home/denis/.m2/repository/org/clojure/spec.alpha/0.2.176/spec.alpha-0.2.176.jar clojure.main
Clojure 1.10.0
user=> (+ 1 2)
3

有关Clojure编译过程的参考文档可能会很有用:https://clojure.org/reference/compilation。要记住的重要一点是在文档的开头:

  

Clojure将您即时加载的所有代码编译为JVM字节码

每次在REPL中定义功能或加载文件时,都会生成一些字节码。这将包括一个或多个.class文件,其中一些可能是实现IFn interface的类。