You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rust中实现Crafting Interpreters的BINARY_OP宏等效功能

问题根因

你写的宏无法识别self是因为Rust采用卫生宏设计,宏内部的标识符不会和调用方作用域的标识符自动绑定,需要显式将self作为参数传入宏,同时你原有的宏里操作数弹出顺序错误,会导致减法、除法这类非交换律运算结果不符合预期。


方案1:调整宏定义实现和C宏等效效果

修正后的宏代码如下:

macro_rules! binop {
    ($self:ident, $op:tt) => {{
        // 先弹右操作数,再弹左操作数,和原书C宏逻辑一致
        let r = $self.stack.pop().unwrap();
        let l = $self.stack.pop().unwrap();
        $self.stack.push(l $op r);
    }};
}

调用方式:

pub fn interpret(&mut self, op: OpCode) {
  match op {
    Op::Add => binop!(self, +),
    Op::Sub => binop!(self, -),
    Op::Mul => binop!(self, *),
    Op::Div => binop!(self, /),
  }
}

如果需要处理栈下溢场景,把代码里的unwrap替换为对应的错误处理逻辑即可。


方案2:更符合Rust风格的零成本无宏实现

不用宏也可以实现完全等效的效果,可读性更好且没有额外性能开销:

// 加inline强制优化,执行效率和宏完全一致
#[inline(always)]
fn binop<F: FnOnce(Value, Value) -> Value>(&mut self, op: F) {
    let r = self.stack.pop().unwrap();
    let l = self.stack.pop().unwrap();
    self.stack.push(op(l, r));
}

调用方式:

pub fn interpret(&mut self, op: OpCode) {
  match op {
    Op::Add => self.binop(|l, r| l + r),
    Op::Sub => self.binop(|l, r| l - r),
    Op::Mul => self.binop(|l, r| l * r),
    Op::Div => self.binop(|l, r| l / r),
  }
}

内容的提问来源于stack exchange,提问作者user9614249

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 18:45:05