题
我想编写一个简单的Ruby DSL翻译一些语句和表达式成另一种语言。一个基本的例子将是:
some_function {
t + 2
}
下面,t不是一个红宝石变量,因此该块不能(和不得!)由红宝石进行评估。所以,我最好的选择是使用解析输出(或AST)做翻译我自己。要做到这一点,我可以使用分析树和ruby2ruby。然而,我有其他构造,我想用,例如:
1.upto(10) {|x|
some_function {
t + x
}
}
在这里,我有一个局部变量,我需要为了做我的翻译得到它的价值。然而,在做了块评价的功能,我没有访问调用块的局部变量。如果它是一个全局变量($ x)的,我可以检查它的名字global_variables数组中,并在最坏的情况下使用eval存在,但我怎么能对一个局部变量这样做,如果有可能的话?
<强>更新强>
刚刚清理的东西。就像我最初说,我使用ruby2ruby(因此分析树)来获得AST(使用to_sexp)对应的块。但使用我的块内的局部变量的情况下,我会遇到以下情况:
[:dvar, :x]
和因此,我需要从它的名字得到一个变量的值作为字符串/符号。和我不能使用的method_missing或instance_eval的,因为我想翻译整个表达式为另一种语言或语法(如RPN)。
不是基于分析树的另一解决方案将是受欢迎的尽管如此,因为它显然不充分使用Ruby 1.9支持。
解决方案
要获得的变量值,使用PROC的结合:
def some_function(&block)
b = block.binding
p [b.eval("t"), b.eval("x")]
end
t = 1
1.upto(10) {|x|
some_function {
t + x
}
}
其他提示
下面,t不是一个红宝石变量和 因此,块不能(绝对不能!) 由红宝石进行评价。
任何原因“未评估”限制?好像 method_missing的会很好地处理评估“失踪” t
可变的,但会红宝石自动取消引用x
变量。
可以使用instance_eval的针对与t
的对象。
class Context
attr_accessor :t
def initialize(_t)
@t = _t
end
end
def some_function(&block)
puts Context.new(1).instance_eval(&block)
end
1.upto(10) {|x|
some_function {
t + x
}
}
不隶属于 StackOverflow