什么时候Ruby中的’eval`是合理的?

“ ‘eval’应该是令人讨厌的吗? ”这启发了这个:

大多数人都同意eval是坏的,并且在大多数情况下更优雅/更安全。

所以我想问一下:如果经常误用eval ,它真的需要作为语言function吗? 这是邪恶而不是好吗?

就个人而言,我发现它唯一有用的地方是插入配置文件中提供的字符串。

编辑:这个问题的目的是在eval是唯一或最佳解决方案时尽可能多地获得真实案例。 所以,请不要进入“应该用语言限制程序员的创造力”的方向。

Edit2:当我说eval时,我当然是指eval ing字符串,而不是将ruby块传递给instance_evalclass_eval

我所知道的唯一情况(除了“我有这个字符串,我想执行它”)是动态处理本地和全局变量。 Ruby有方法来获取局部变量和全局变量的名称,但是缺少基于这些名称来获取或设置其值的方法。 进行AFAIK的唯一方法是使用eval

任何其他用途几乎肯定是错误的。 我不是大师,也不能明确说明没有其他人,但是我曾经见过的其他一些用例,有人说“你需要eval,”我找到了一个没有的解决方案。

请注意,顺便说一句,我在这里谈论字符串eval 。 Ruby也有instance_eval ,它可以在接收器的上下文中执行字符串或块。 这种方法的块forms快速,安全且非常有用。

什么时候有道理? 我会说什么时候没有合理的选择。 我能够想到一个我无法想到替代方案的用途:irb,如果你挖得足够深(对于workspace.rb ,如果你感兴趣的话,我的副本中的80行左右)使用eval来执行你的输入:

 def evaluate(context, statements, file = __FILE__, line = __LINE__) eval(statements, @binding, file, line) end 

这对我来说似乎很合理 – 在你被要求这样做的那一刻,你特别不知道你要执行什么代码的情况。 动态和互动的东西似乎符合要求。

eval存在的原因是因为当你需要它时,当你真正需要它时,没有替代品。 毕竟,只有通过创造性方法调度才能做到这么多,并且在某些时候你需要执行任意代码。

仅仅因为语言具有可能危险的特征并不意味着它本身就是一件坏事。 当一种语言假设比其用户更多时,就会遇到麻烦。

我认为当你发现一种没有危险的编程语言时,你会找到一种不太有用的编程语言。

eval何时合理? 用务实的话来说,当你说的时候。 如果它是您的程序并且您是程序员,则可以设置参数。

eval()有一个非常重要的用例,它不能使用任何其他东西来实现(AFAIK),那就是找到绑定的相应对象引用。

假设您已经传递了一个块但是(由于某种原因)您需要访问绑定的对象上下文,您将执行以下操作:

 obj = eval('self', block.binding) 

定义以下内容也很有用:

 class Proc def __context__ eval('self', self.binding) end end 

IMO主要用于域特定语言。

“ Ruby中的评估选项 ”是Jay Fields关于InfoQ的文章。

eval是一种工具,它本身既不好也不邪恶。 只要您确定它是您要完成的工作的正确工具,这是合理的。

像eval这样的工具是关于在运行时评估代码与“编译”时间。 你知道启动Ruby时代码是什么吗? 那么你可能不需要eval。 您的代码是否在运行时生成代码? 那么你可能需要评估它。

例如,递归代码解析器中所需的方法/函数取决于要解析的语言。 如果您的应用程序在运行中构建这样的解析器,那么使用eval可能是有意义的。 您可以编写一个通用解析器,但它可能不是一个优雅的解决方案。

“ 在Scheme.Macros或eval?中以编程方式填写letrec ”是我在Scheme中发布的关于eval的问题,其中使用它几乎是不可避免的。

通常,当您想要运行任意代码时, eval是一种有用的语言function。 这应该是一件罕见的事情,但也许您正在制作自己的REPL,或者您希望由于某种原因向最终用户公开ruby运行时。 它可能发生,这就是该function存在的原因。 如果您使用它来解决语言的某些部分(例如全局变量),那么语言是有缺陷的,或者您对语言的理解是有缺陷的。 解决方案通常不使用eval,而是要更好地理解语言或选择不同的语言。

值得注意的是,在ruby中, instance_evalclass_eval还有其他用途。