I know send takes string or symbol with arguments while instance_eval takes string or block, and their difference could be apparent given receivers.
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'
send is a Ruby method allowing to invoke another method by name passing it any arguments specified.
instance_eval(array_second) adds the method second to the variable a — which is an instance of Array — by passing a String that will be evaluated in the context of the instance a . The call to str. instance_eval with a block will evaluate the content of the block in the context of str — which is an instance of String .
From the fine manual:
send(symbol [, args...]) → obj
send(string [, args...]) → objInvokes the method identified by symbol, passing it any arguments specified. [...] When the method is identified by a string, the string is converted to a symbol.
and for instance_eval
:
instance_eval(string [, filename [, lineno]] ) → obj
instance_eval {| | block } → objEvaluates a string containing Ruby source code, or the given block, within the context of the receiver (obj). 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.
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.
In your case, there isn't much difference as the string you're handing to instance_eval
is just a single method. 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.
You might also be interested in Object#public_send
and BasicObject#__send__
Whatever you can do with send
is a proper subset of that of 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. So whenever you have send
, you can rewrite it with instance_eval
, but not vice versa.
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.
In your example, the result will be the same, but the first one will run faster.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With