Rascal的eval调用自定义代数数据类型报未声明变量错误咨询
报错原因
Rascal 的 eval 函数默认使用独立的干净执行上下文,不会继承当前模块的类型定义、导入依赖,所以你在表达式里用到的 dog、cat 构造函数在 eval 的上下文中没有被声明,就会抛出未定义错误。
解决方案1:继承当前模块上下文(无需在eval内重复导入)
util::Eval 模块的 eval 函数提供了 imports 参数,可以指定 eval 执行时自动导入的模块,你只需要把当前模块的位置传入,就可以复用当前模块所有的定义:
// 仅需修改eval调用行,添加imports参数即可 Result[bool] re = eval(#bool, "[*_, cat(), *_] := [dog(), cat()];", imports={|PuzzleScript::Test::Engine::EvalExample|});
修改后执行即可正常输出 True 2。
解决方案2:避免使用eval的动态模式匹配实现
你不需要依靠拼接字符串+eval实现动态模式匹配,Rascal 支持更安全高效的原生实现方式:
- 如果是简单的动态匹配目标场景:直接用高阶函数传参即可,比如你需要动态指定要匹配的元素,直接将元素作为参数传入匹配函数:
// 通用列表匹配函数,无需eval bool hasTarget<T>(list<T> input, T target) { return [*_, target, *_] := input; } // 调用示例 println(hasTarget([dog(), cat()], cat()) ? "True 2" : "False 2");
- 如果是复杂度更高的动态模式(比如动态决定匹配位置、匹配规则数量),可以用Rascal的元编程API构造模式语法树,再编译成可执行函数,性能和安全性都远高于eval,同时天然继承当前模块的上下文,不需要额外处理导入问题。
内容的提问来源于stack exchange,提问作者Clement Julia
相关产品推荐
相关产品推荐

