也许我只是一个来自不同学校的纯粹主义者,但我一般来说对基于字符串的“eval”结构过敏.给出一个绑定对象,是否有任何方法可以安全地执行以下任何操作:一般情况下:
>在绑定表示的上下文中列出范围中的标识符,或检索内容的散列.
>将绑定中的局部变量的值设置为外部上下文中某个局部变量的值.理想情况下,即使值是对象引用,文件句柄,还是其他一些复杂的实体,这应该是一般的.
>(extension 2 :)给定一个哈希,在每个条目的绑定中设置locals.
>更好的是,给定一个哈希构建一个只有基本语言结构和范围中的哈希中的名称的绑定.
基本上,我想知道哪些是可能的,以及如何完成那些.我想像,每个方案的解决方案将是相当密切相关的,这就是为什么我将所有这一切都放在一个单一的问题.
或者,有没有办法在绑定的上下文中已经解析的eval代码,类似于Perl的eval BLOCK语法?
解决方法
基于:http://wikis.onestepback.org/index.cgi/Tech/Ruby/RubyBindings.rdoc/style/print
其余的是Jim Shubert有用的指点后的实验.
>这可以通过在绑定中评估local_variables,instance_variables和global_variables来实现.
>你可以做一些如下所述的事情,给定var_name,new_val,my_binding(语法可能是不完美的或可改进的,在评论中可以自由地提出建议.另外,我无法获得列表中的代码格式化,建议如何这样做也会实施.)
>你可以直接(2)并循环哈希来做到这一点.
>请参见下面的第二个代码块.这个想法是从TOPLEVEL_BINDING开始,我相信通常只包括全局变量.
这确实涉及使用字符串eval.然而,没有变量值被扩展到所涉及的字符串,所以如果按照描述使用,它应该是相当安全的,并且应该用于“传入”复杂的变量值.
还要注意的是,可以使用eval var_name,my_binding来获取变量的值.请注意,在所有这些使用中,变量的名称对于eval是安全的,因此它最好不应该来自任何类型的用户输入.
在一个绑定中设置变量赋值var_name,my_binding:
# the assignment to nil in the eval coerces the variable into existence at the outer scope setter = eval "#{var_name} = nil; lambda { |v| #{var_name} = v }",my_binding setter.call(new_val)
构建“定制”绑定:
my_binding = eval "lambda { binding }",TOPLEVEL_BINDING # build a nearly-empty binding # set_in_binding is based on the above snippet vars_to_include.each { |var_name,new_val| set_in_binding(var_name,my_binding) }