#java #eval
#java #eval
Вопрос:
Привет всем, недавно я наткнулся на библиотеку Arity -> источник можно найти здесь и обнаружил, что она оценивает строку как арифметическую операцию с использованием метода .eval(), посмотрев на источник, я нашел этот метод объекта Symbols:
/**
Evaluates a simple expression (such as "1 1") and returns its value.
@throws SyntaxException in these cases:
<ul>
<li> the expression is not well-formed
<li> the expression is a definition (such as "a=1 1")
<li> the expression is an implicit function (such as "x 1")
</ul>
*/
public synchronized double eval(String expression) throws SyntaxException {
return compiler.compileSimple(this, expression).eval();
}
Этот метод вызывает .compileSimple объекта компиляции компилятора:
Function compileSimple(Symbols symbols, String expression) throws SyntaxException {
rpn.setConsumer(simpleCodeGen.setSymbols(symbols));
lexer.scan(expression, rpn);
return simpleCodeGen.getFun();
}
Которая возвращает объект функции, а затем вызывает для него метод eval(). Глядя на метод Function.eval(), я увидел это:
/**
Evaluates an arity-0 function (a function with no arguments).
@return the value of the function
*/
public double eval() {
throw new ArityException(0);
}
Метод eval должен возвращать тип double, а реализация выдает исключение ArityException, которое имеет эту реализацию:
public class ArityException extends RuntimeException {
public ArityException(String mes) {
super(mes);
}
public ArityException(int nArgs) {
this("Didn't expect " nArgs " arguments");
}
}
Но когда генерируется исключение ArityException, оно вызывает конструктор super() исключения RuntimeException, и это исключение, и не возвращается double, как должно быть, возможно, я перепутал некоторые отрывки, но я не понял, что последнее исключение ArityException равно 0 внутри реализации Function.eval() .
Итак, как это действительно работает?
Ответ №1:
Вы пропустили объявление simpleCodeGen
:
private final SimpleCodeGen simpleCodeGen = new SimpleCodeGen(exception);
Это означает, что compileSimple(...)
на самом деле возвращает a CompiledFunction
, который расширяет ContextFunction
и тому подобное Function
.
CompiledFunction getFun() {
return new CompiledFunction(0, code.toArray(), consts.getRe(), consts.getIm(), funcs.toArray());
}
Так eval(...)
что на самом деле это ContextFunction
вызываемая функция. У этого есть реальная реализация.
Выполнение анализа кода без IDE и просто просмотр кода могут быть сложными. Использование отладчика и пошаговое выполнение легко покажет вам поток программы.
Комментарии:
1. Спасибо за объяснение!