# Is this possible in Ruby

**URL:** <https://www.ruby-forum.com/t/is-this-possible-in-ruby/159276>\
**Category:** Ruby\
**Created:** [February 2, 2009, 11:49pm UTC](https://www.ruby-forum.com/t/is-this-possible-in-ruby/159276 "2009-02-02T23:49:37Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![ther](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/977dab/32.png) [@ther](https://www.ruby-forum.com/u/ther)\
**Post date:** [February 2, 2009, 11:49pm UTC](https://www.ruby-forum.com/t/is-this-possible-in-ruby/159276/1 "2009-02-02T23:49:37Z")

</div>

Just an idea which may come in handy. Can this be done and how in Ruby.

def calc(what)  
some\_eval(what)  
end

a=10  
b=12  
calc(‘a+b’) # expression as parameters  
=\> 12 # would return

a=‘aa’  
b=‘bb’  
calc(‘a+b’)  
=\> ‘aabb’

This is of course strictly hypothetical. I would like the expression to  
be evaluated inside the method using variables which are local to the  
calling part.

by  
TheR

---

<div class="post-metadata">

**Author:** ![ther](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/977dab/32.png) [@ther](https://www.ruby-forum.com/u/ther)\
**Post date:** [February 3, 2009, 12:34am UTC](https://www.ruby-forum.com/t/is-this-possible-in-ruby/159276/2 "2009-02-03T00:34:16Z")

</div>

On Mon, Feb 2, 2009 at 10:49 PM, Damjan R. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> =\> 12 # would return
> 
> by  
> TheR

ruby 1.9 comes with Binding#eval. In 1.8.6 you can do this:

class Binding  
def eval(str)  
Kernel.eval(str, self)  
end  
end

a = 10  
b = 12  
binding.eval(‘a + b’) # =\> 22

def another(c, d)  
binding.eval(‘c + d’)  
end  
another(20, 22) # =\> 42

Regards,  
Sean

---

<div class="post-metadata">

**Author:** ![ther](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/977dab/32.png) [@ther](https://www.ruby-forum.com/u/ther)\
**Post date:** [February 3, 2009, 1:12am UTC](https://www.ruby-forum.com/t/is-this-possible-in-ruby/159276/3 "2009-02-03T01:12:52Z")

</div>

On Feb 2, 2009, at 6:33 PM, “Sean O’Halpin” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> > b=12  
> > be evaluated inside the method using variables which are local to the  
> > Kernel.eval(str, self)  
> > another(20, 22) # =\> 42
> 
> Regards,  
> Sean

I thought in 1.8.6 it could be done… Not positive though

a, b = 3, 5  
formula=“a\*b”  
p eval(formula)

---

<div class="post-metadata">

**Author:** ![ther](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/977dab/32.png) [@ther](https://www.ruby-forum.com/u/ther)\
**Post date:** [February 3, 2009, 1:40am UTC](https://www.ruby-forum.com/t/is-this-possible-in-ruby/159276/4 "2009-02-03T01:40:58Z")

</div>

On Tue, Feb 3, 2009 at 12:12 AM, List.rb [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I thought in 1.8.6 it could be done… Not positive though
> 
> a, b = 3, 5  
> formula=“a\*b”  
> p eval(formula)

D’oh. You’re absolutely right. Maybe I was thinking of this:

a = 1  
b = 2  
def some\_eval(context)  
eval(‘a + b’, context)  
end

some\_eval(binding) # =\> 3

Late night. Off to bed 🙂

Regards,  
Sean

---

<div class="post-metadata">

**Author:** ![ther](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/977dab/32.png) [@ther](https://www.ruby-forum.com/u/ther)\
**Post date:** [February 3, 2009, 11:06am UTC](https://www.ruby-forum.com/t/is-this-possible-in-ruby/159276/5 "2009-02-03T11:06:41Z")

</div>

2009/2/2 Damjan R. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> =\> 12 # would return
> 
> a=‘aa’  
> b=‘bb’  
> calc(‘a+b’)  
> =\> ‘aabb’
> 
> This is of course strictly hypothetical. I would like the expression to  
> be evaluated inside the method using variables which are local to the  
> calling part.

As has been demonstrated you need the binding of the context in which  
you want to evaluate your expression string. I see two options.

1. explicitly, i.e.

def calc(what, bind)  
eval(what, bind)  
end

but this is pointless as “calc” is just an alias for “eval”.

1. implicitly

You can keep track of bindings by implementing a trace function (see  
set\_trace\_func). Argument 4 is the current binding and you can place  
them in a thread local stack, e.g.

# untested

set\_trace\_func lambda {|\*a|  
case a.first  
when /call$/  
(Thread.current[:bindings] ||= []).push(a[4])  
when /return$/  
Thread.current[:bindings].pop  
end  
}

def calc(s)  
eval(s, Thread.current[:bindings][-2])  
end

Kind regards

robert
