gpt4 book ai didi

java - Java 解释器中数学运算的抽象

转载 作者:行者123 更新时间:2023-12-01 19:35:58 25 4
gpt4 key购买 nike

我正在用 Java 编写 AST 解释器,它有很多方法可以检查参数类型并在匹配时执行操作。到目前为止,有超过五种方法基本上是彼此复制粘贴的版本。有没有办法抽象要检查的类型和要执行的操作?

    @Override
public Object visitMultiplyNode(MultiplyNode multiplyNode) {
Object lhs = multiplyNode.getLeftHandSide().accept(this);
Object rhs = multiplyNode.getRightHandSide().accept(this);

if (lhs instanceof Double && rhs instanceof Double) {
return (double) lhs * (double) rhs;
}
if (lhs instanceof Long && rhs instanceof Long) {
return (long) lhs * (long) rhs;
}
throw new TypeError("Can not multiply " + lhs.getClass() + " and " + rhs.getClass() + ".");
}

我想要检查的类型并不总是相同,例如模数节点仅接受长整型,而加法节点也接受字符串进行连接。

    @Override
public Object visitAddNode(AddNode addNode) {
Object lhs = addNode.getLeftHandSide().accept(this);
Object rhs = addNode.getRightHandSide().accept(this);

if (lhs instanceof Double && rhs instanceof Double) {
return (double) lhs + (double) rhs;
}
if (lhs instanceof Long && rhs instanceof Long) {
return (long) lhs + (long) rhs;
}
if (lhs instanceof String && rhs instanceof String) {
return "" + lhs + lhs;
}
throw new TypeError("Can not add " + lhs.getClass() + " and " + rhs.getClass() + ".");
}

@Override
public Object visitModulusNode(ModulusNode modulusNode) {
Object lhs = modulusNode.getLeftHandSide().accept(this);
Object rhs = modulusNode.getRightHandSide().accept(this);

if (lhs instanceof Long && rhs instanceof Long) {
return (long) lhs % (long) rhs;
}
throw new TypeError("Can not take modulus of " + lhs.getClass() + " and " + rhs.getClass() + ".");
}

最佳答案

你可以使用 lambda:

private Object visitBinaryOperatorNode(BinaryOpNode node, BiFunction<T, T> op) {
Object lhs = node.getLeftHandSide().accept(this);
Object rhs = node.getRightHandSide().accept(this);

if (lhs instanceof Long && rhs instanceof Long) {
return op.apply((long) lhs, (long) rhs);
}
throw new TypeError("Can not take " + node.getOpName() + "of " + lhs.getClass() + " and " + rhs.getClass() + ".");
}

但是,由于您支持某些运算符的多种类型,因此您需要另一层抽象:

@RequiredArgsConstructor// Lombok, otherwise write the boilerplate yourself
public class BinaryOperator<T, T> {
@NonNull private final BiFunction<T, T> op;
@NonNull private final Class<T> clazz;

public boolean isApplicable(Object left, Object right) {
return clazz.isInstance(left) && clazz.isInstance(right);
}

public T apply(Object left, Object right) {
return op.apply(clazz.cast(left), clazz.cast(right));
}
}

您现在可以传递一堆有效的二元运算符并测试它们是否适用,如果适用,则应用它们。

private static final List<BinaryOperator<?, ?>> VALID_ADD_OPERATORS = Arrays.asList(
new BinaryOperator<>((x, y) -> x + y, Double.class),
new BinaryOperator<>((x, y) -> x + y, Long.class),
new BinaryOperator<>((x, y) -> x + y, String.class)
);

private static final List<BinaryOperator<?, ?>> VALID_MULTIPLY_OPERATORS = Arrays.asList(
new BinaryOperator<>((x, y) -> x * y, Double.class),
new BinaryOperator<>((x, y) -> x * y, Long.class)
);

@Override
public Object visitAddNode(AddNode addNode) {
return visitBinaryOperatorNode(addNode, VALID_ADD_OPERATORS );
}

@Override
public Object visitMultiplyNode(MultiplyNode multiplyNode) {
return visitBinaryOperatorNode(multiplyNode, VALID_MULTIPLY_OPERATORS );
}

private Object visitBinaryOperatorNode(BinaryOpNode node, List<BinaryOperator<?, ?>> validOperators) {
Object lhs = node.getLeftHandSide().accept(this);
Object rhs = node.getRightHandSide().accept(this);

for (BinaryOperator<?, ?> op : validOperators) {
if (op.isApplicable(lhs, rhs)) return op.apply(lhs, rhs);
}
throw new TypeError("Can not take " + node.getOpName() + "of " + lhs.getClass() + " and " + rhs.getClass() + ".");
}

关于java - Java 解释器中数学运算的抽象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57542718/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com