2017-02-05 3 views
0

Я следую this series, чтобы узнать, как работает компилятор clojure.Как вызвать StaticMethodExpr.eval?

Я пытался вызвать eval метод StaticMethodExpr с использованием кодов ниже

(ns clojure.lang 
    (:use clojure.core) 
    (:import [clojure.lang Compiler Compiler$C])) 

(def form (read-string "(+ 1 1)")) 

(def expr (Compiler/analyze Compiler$C/EXPRESSION form)) 

(.eval expr) 

, но не повезло и бросить IllegalArgumentException:

Unhandled java.lang.IllegalArgumentException 
    Can't call public method of non-public class: public 
    java.lang.Object clojure.lang.Compiler$StaticMethodExpr.eval() 

Есть что-нибудь мне не хватает или это a bug in jdk?

ответ

1

Вы все еще можете вызвать метод с помощью отражения:

(let [m (.getDeclaredMethod clojure.lang.Compiler$Expr "eval" (make-array Class 0))] 
    (.setAccessible m true) 
    (defn -eval [expr] 
    (.invoke m expr (object-array 0)))) 

(-eval (clojure.lang.Compiler/analyze clojure.lang.Compiler$C/EXPRESSION '(+ 1 2))) 
;= 3 

Это должно быть достаточно хорошо, если ваша цель состоит в том, чтобы исследовать.

Отражением-бесплатная программа Java может вызвать этот метод, по результатам анализа (+ 1 2) через ссылку типа clojure.lang.Compiler.HostExpr, что публика, хотя ни объявляющего интерфейс clojure.lang.Compiler.Expr, ни фактического типа исполнения являются публичными, так что я полагаю, несколько удивительно, что требуется setAccessible.

Смежные вопросы