使用nil上下文的quote do代码无效,是否有替代实现方案?
Elixir无上下文quote生成自由变量AST的问题
你的问题代码:
ast = quote context: nil do x = y end Code.eval_quoted(ast, y: 2)
你期望生成的AST为:{:=, [], [{:x, [], nil}, {:y, [], nil}]},让Code.eval_quoted能从绑定中读取y的值,这个需求可以实现,不需要创建上下文,问题出在quote context: nil对未绑定变量的解析逻辑上。
解决方法
方法1:用var!/1显式声明自由变量
在quote块里用var!/1标记变量为自由变量,告诉Elixir不要在当前上下文解析它,而是保留为变量节点:
ast = quote context: nil do x = var!(y) end Code.eval_quoted(ast, y: 2) # 运行结果:{2, [x: 2, y: 2]}
此时生成的AST就是你期望的{:=, [], [{:x, [], nil}, {:y, [], nil}]}。
方法2:用Macro.var/2构造变量节点
通过Macro.var/2手动指定变量的上下文为nil,确保y被解析为自由变量:
ast = quote do x = unquote(Macro.var(:y, nil)) end # 生成的AST符合预期 Code.eval_quoted(ast, y: 2)
原代码失败的原因
当quote context: nil时,Elixir无法确定y的归属上下文,会把它当作未定义的函数调用(AST形式为{:y, [], []}),而非变量节点,所以Code.eval_quoted运行时会抛出错误,因为找不到y/0函数。
内容的提问来源于stack exchange,提问作者doobdargent
相关产品推荐
相关产品推荐

