简体   繁体   English

send和instance_eval之间的Ruby差异?

[英]Ruby difference between send and instance_eval?

I know send takes string or symbol with arguments while instance_eval takes string or block, and their difference could be apparent given receivers. 我知道send接受带有参数的字符串或符号,而instance_eval接受字符串或块,并且给定接收器它们的区别可能很明显。

My question is what the ' under the hood ' difference is for the example below? 我的问题是下面的例子中“引擎盖下 ”的区别是什么?

1234.send 'to_s'               # '1234'
1234.instance_eval 'to_s'      # '1234'

From the fine manual : 精细手册

send(symbol [, args...]) → obj 发送(符号[,args ...])→obj
send(string [, args...]) → obj send(string [,args ...])→obj

Invokes the method identified by symbol , passing it any arguments specified. 调用由symbol标识的方法,并将指定的任何参数传递给它。 [...] When the method is identified by a string, the string is converted to a symbol. [...]当通过字符串标识方法时,字符串将转换为符号。

and for instance_eval : instance_eval

instance_eval(string [, filename [, lineno]] ) → obj instance_eval(string [,filename [,lineno]])→obj
instance_eval {| instance_eval {| | | block } → obj block}→obj

Evaluates a string containing Ruby source code, or the given block, within the context of the receiver ( obj ). 在接收器( obj )的上下文中计算包含Ruby源代码或给定块的字符串。 In order to set the context, the variable self is set to obj while the code is executing, giving the code access to obj ’s instance variables. 为了设置上下文,在代码执行时将变量self设置为obj ,使代码可以访问obj的实例变量。

So send executes a method whereas instance_eval executes an arbitrary block of code (as a string or block) with self set to the object that you're calling instance_eval on. 因此send执行一个方法,而instance_eval执行任意代码块(作为字符串或块),并将self设置为您正在调用instance_eval的对象。

In your case, there isn't much difference as the string you're handing to instance_eval is just a single method. 在您的情况下,没有太大的区别,因为您要处理的字符串instance_eval只是一个方法。 The main difference is that anyone reading your code (including you in six months) will be wondering why you're using instance_eval to call a single method. 主要区别在于,任何阅读代码的人(包括六个月内的代码)都会想知道为什么要使用instance_eval来调用单个方法。

You might also be interested in Object#public_send and BasicObject#__send__ 您可能也对Object#public_sendBasicObject#__send__

Whatever you can do with send is a proper subset of that of instance_eval . 无论你使用send做什么都是instance_eval的适当子集。 Namely, the argument to send has to be a single method (and its arguments), whereas the argument to instance_method is an arbitrary code. 也就是说, send的参数必须是单个方法(及其参数),而instance_method的参数是任意代码。 So whenever you have send , you can rewrite it with instance_eval , but not vice versa. 因此,无论何时send ,都可以使用instance_eval重写它,但反之亦然。

However, performancewise, send is much faster than instance_eval since there is no additional parsing required to execute send , whereas instance_eval needs to parse the whole argument. 但是,在性能方面, sendinstance_eval快得多,因为执行send不需要额外的解析,而instance_eval需要解析整个参数。

In your example, the result will be the same, but the first one will run faster. 在您的示例中,结果将是相同的,但第一个将运行得更快。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM