# Evaluating a string of Ruby code within an anonymous module: done correctly?

**URL:** <https://rubytalk.org/t/evaluating-a-string-of-ruby-code-within-an-anonymous-module-done-correctly/16556>\
**Category:** ruby-talk\
**Created:** [17 February 2005 18:54 UTC](https://rubytalk.org/t/evaluating-a-string-of-ruby-code-within-an-anonymous-module-done-correctly/16556 "2005-02-17T18:54:52Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Asfand\_Yar\_Qazi1](https://avatars.discourse-cdn.com/v4/letter/a/e36b37/32.png) [@Asfand\_Yar\_Qazi1](https://rubytalk.org/u/Asfand_Yar_Qazi1)\
**Post date:** [17 February 2005 18:54 UTC](https://rubytalk.org/t/evaluating-a-string-of-ruby-code-within-an-anonymous-module-done-correctly/16556/1 "2005-02-17T18:54:52Z")

</div>

Hi,

I'd like to evaluate a string of Ruby code (stored in a YAML file, as it happens) safely. Note the purpose is simply to avoid variable name clashes and stop lots of eval'ed Ruby code from overloading the heap with lots of objects (i.e. when the anonymous module is deleted, the temporary variables defined within it are also gone.)

The purpose is NOT for safety reasons, so we don't have to worry about that.

Am I doing it the right way? Or does anybody know a better way? Any better way of passing in arguments to the code in the string?

Anyway, here goes:

def eval\_string(s, \*args\_to\_pass)  
&nbsp;&nbsp;m = Module.new  
&nbsp;&nbsp;m.const\_set("ARGS", arg\_to\_pass)  
&nbsp;&nbsp;m.class\_eval(s.to\_str)  
end # Soon m will be GC'ed, and all temp objects gone! MUHAHA

s.eval\_string(\<\<EOL, [1, 2, 3, 4, 5])  
a = ARGS  
b = a.collect {|i| i\*3}  
c = b.join("||")  
puts(c)  
EOL

Thanks,  
&nbsp;&nbsp;Asfand Yar

---

<div class="post-metadata">

**Author:** ![Asfand\_Yar\_Qazi1](https://avatars.discourse-cdn.com/v4/letter/a/e36b37/32.png) [@Asfand\_Yar\_Qazi1](https://rubytalk.org/u/Asfand_Yar_Qazi1)\
**Post date:** [17 February 2005 19:44 UTC](https://rubytalk.org/t/evaluating-a-string-of-ruby-code-within-an-anonymous-module-done-correctly/16556/2 "2005-02-17T19:44:48Z")

</div>

Asfand Yar Qazi wrote:

> Hi,
> 
> I'd like to evaluate a string of Ruby code (stored in a YAML file, as it happens) safely. Note the purpose is simply to avoid variable name clashes and stop lots of eval'ed Ruby code from overloading the heap with lots of objects (i.e. when the anonymous module is deleted, the temporary variables defined within it are also gone.)
> 
> The purpose is NOT for safety reasons, so we don't have to worry about that.
> 
> Am I doing it the right way? Or does anybody know a better way? Any better way of passing in arguments to the code in the string?

Actually, I forgot to mention the other main very important reason for doing it this way: passing arguments to the eval'ed code. Also, I may need to be able to eval several strings at once (kind of) so storing the arguments in global variables is also a no-no.

> **···**
>
> > Anyway, here goes:
> > 
> > def eval\_string(s, \*args\_to\_pass)  
> > &nbsp;&nbsp;&nbsp;&nbsp;m = Module.new  
> > &nbsp;&nbsp;&nbsp;&nbsp;m.const\_set("ARGS", arg\_to\_pass)  
> > &nbsp;&nbsp;&nbsp;&nbsp;m.class\_eval(s.to\_str)  
> > end # Soon m will be GC'ed, and all temp objects gone! MUHAHA
> > 
> > s.eval\_string(\<\<EOL, [1, 2, 3, 4, 5])  
> > a = ARGS  
> > b = a.collect {|i| i\*3}  
> > c = b.join("||")  
> > puts(c)  
> > EOL
> > 
> > Thanks,  
> > &nbsp;&nbsp;&nbsp;&nbsp;Asfand Yar

---

<div class="post-metadata">

**Author:** ![Joel\_VanderWerf1](https://avatars.discourse-cdn.com/v4/letter/j/94ad74/32.png) [@Joel\_VanderWerf1](https://rubytalk.org/u/Joel_VanderWerf1)\
**Post date:** [17 February 2005 20:17 UTC](https://rubytalk.org/t/evaluating-a-string-of-ruby-code-within-an-anonymous-module-done-correctly/16556/3 "2005-02-17T20:17:24Z")

</div>

Asfand Yar Qazi wrote:

> Hi,
> 
> I'd like to evaluate a string of Ruby code (stored in a YAML file, as it happens) safely. Note the purpose is simply to avoid variable name clashes and stop lots of eval'ed Ruby code from overloading the heap with lots of objects (i.e. when the anonymous module is deleted, the temporary variables defined within it are also gone.)
> 
> The purpose is NOT for safety reasons, so we don't have to worry about that.
> 
> Am I doing it the right way? Or does anybody know a better way? Any better way of passing in arguments to the code in the string?
> 
> Anyway, here goes:
> 
> def eval\_string(s, \*args\_to\_pass)  
> &nbsp;&nbsp;&nbsp;&nbsp;m = Module.new  
> &nbsp;&nbsp;&nbsp;&nbsp;m.const\_set("ARGS", arg\_to\_pass)  
> &nbsp;&nbsp;&nbsp;&nbsp;m.class\_eval(s.to\_str)  
> end # Soon m will be GC'ed, and all temp objects gone! MUHAHA
> 
> s.eval\_string(\<\<EOL, [1, 2, 3, 4, 5])  
> a = ARGS  
> b = a.collect {|i| i\*3}  
> c = b.join("||")  
> puts(c)  
> EOL

Here's another way of passing in args, using a fixed method name ("main") rather than a fixed constant name ("ARGS"):

def eval\_string(s, \*args\_to\_pass)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m = Module.new  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def m.method\_added(name)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module\_function(name)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m.class\_eval(s.to\_str)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m.main(\*args\_to\_pass)  
end

eval\_string(\<\<EOL, [1, 2, 3, 4, 5])  
&nbsp;&nbsp;&nbsp;def main(\*args)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b = args.collect {|i| i\*3}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c = b.join("||")  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts(c)  
&nbsp;&nbsp;&nbsp;end  
EOL

That's nice if you want to break up main into several methods, define constants, etc.

Here's an even simpler way, just wrapping the code in a proc, which may be suitable for small snippets of code:

def eval\_string(s, \*args\_to\_pass)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pr = eval("proc do |\*args| #{s.to\_str} end")  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pr[\*args\_to\_pass]  
end

eval\_string(\<\<EOL, [1, 2, 3, 4, 5])  
&nbsp;&nbsp;&nbsp;b = args.collect {|i| i\*3}  
&nbsp;&nbsp;&nbsp;c = b.join("||")  
&nbsp;&nbsp;&nbsp;puts(c)  
EOL

Warning: the binding of the "pr" local variable and the two arg variables is still in effect wthin the proc, so this may not be suitable. Or you could use very obscure names and hope.

---

<div class="post-metadata">

**Author:** ![Joel\_VanderWerf1](https://avatars.discourse-cdn.com/v4/letter/j/94ad74/32.png) [@Joel\_VanderWerf1](https://rubytalk.org/u/Joel_VanderWerf1)\
**Post date:** [17 February 2005 20:22 UTC](https://rubytalk.org/t/evaluating-a-string-of-ruby-code-within-an-anonymous-module-done-correctly/16556/4 "2005-02-17T20:22:37Z")

</div>

Joel VanderWerf wrote:

> Here's an even simpler way, just wrapping the code in a proc, which may be suitable for small snippets of code:
> 
> def eval\_string(s, \*args\_to\_pass)  
> &nbsp;&nbsp;&nbsp;&nbsp;pr = eval("proc do |\*args| #{s.to\_str} end")  
> &nbsp;&nbsp;&nbsp;&nbsp;pr[\*args\_to\_pass]  
> end
> 
> eval\_string(\<\<EOL, [1, 2, 3, 4, 5])  
> &nbsp;&nbsp;b = args.collect {|i| i\*3}  
> &nbsp;&nbsp;c = b.join("||")  
> &nbsp;&nbsp;puts(c)  
> EOL
> 
> Warning: the binding of the "pr" local variable and the two arg variables is still in effect wthin the proc, so this may not be suitable. Or you could use very obscure names and hope.

Just realized how to fix that:

def empty\_binding  
&nbsp;&nbsp;&nbsp;binding  
end

def eval\_string(s, \*args\_to\_pass)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pr = eval("proc do |\*args| #{s.to\_str} end", empty\_binding)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pr[\*args\_to\_pass]  
end

eval\_string(\<\<EOL, [1, 2, 3, 4, 5])  
&nbsp;&nbsp;&nbsp;b = args.collect {|i| i\*3}  
&nbsp;&nbsp;&nbsp;c = b.join("||")  
&nbsp;&nbsp;&nbsp;puts(c)  
&nbsp;&nbsp;&nbsp;#p pr #\<-- now this fails  
EOL

---

<div class="post-metadata">

**Author:** ![Asfand\_Yar\_Qazi1](https://avatars.discourse-cdn.com/v4/letter/a/e36b37/32.png) [@Asfand\_Yar\_Qazi1](https://rubytalk.org/u/Asfand_Yar_Qazi1)\
**Post date:** [17 February 2005 21:04 UTC](https://rubytalk.org/t/evaluating-a-string-of-ruby-code-within-an-anonymous-module-done-correctly/16556/5 "2005-02-17T21:04:53Z")

</div>

Joel VanderWerf wrote:

> Joel VanderWerf wrote:
> 
> > Here's an even simpler way, just wrapping the code in a proc, which may be suitable for small snippets of code:
> > 
> > def eval\_string(s, \*args\_to\_pass)  
> > &nbsp;&nbsp;&nbsp;&nbsp;pr = eval("proc do |\*args| #{s.to\_str} end")  
> > &nbsp;&nbsp;&nbsp;&nbsp;pr[\*args\_to\_pass]  
> > end
> > 
> > eval\_string(\<\<EOL, [1, 2, 3, 4, 5])  
> > &nbsp;&nbsp;b = args.collect {|i| i\*3}  
> > &nbsp;&nbsp;c = b.join("||")  
> > &nbsp;&nbsp;puts(c)  
> > EOL
> > 
> > Warning: the binding of the "pr" local variable and the two arg variables is still in effect wthin the proc, so this may not be suitable. Or you could use very obscure names and hope.
> 
> Just realized how to fix that:
> 
> def empty\_binding  
> &nbsp;&nbsp;binding  
> end
> 
> def eval\_string(s, \*args\_to\_pass)  
> &nbsp;&nbsp;&nbsp;&nbsp;pr = eval("proc do |\*args| #{s.to\_str} end", empty\_binding)  
> &nbsp;&nbsp;&nbsp;&nbsp;pr[\*args\_to\_pass]  
> end
> 
> eval\_string(\<\<EOL, [1, 2, 3, 4, 5])  
> &nbsp;&nbsp;b = args.collect {|i| i\*3}  
> &nbsp;&nbsp;c = b.join("||")  
> &nbsp;&nbsp;puts(c)  
> &nbsp;&nbsp;#p pr #\<-- now this fails  
> EOL

I think I like this method best. very nice!

Thanks

---

<div class="post-metadata">

**Author:** ![Asfand\_Yar\_Qazi1](https://avatars.discourse-cdn.com/v4/letter/a/e36b37/32.png) [@Asfand\_Yar\_Qazi1](https://rubytalk.org/u/Asfand_Yar_Qazi1)\
**Post date:** [17 February 2005 21:14 UTC](https://rubytalk.org/t/evaluating-a-string-of-ruby-code-within-an-anonymous-module-done-correctly/16556/6 "2005-02-17T21:14:48Z")

</div>

Asfand Yar Qazi wrote:

> > Just realized how to fix that:
> > 
> > def empty\_binding  
> > &nbsp;&nbsp;binding  
> > end
> > 
> > def eval\_string(s, \*args\_to\_pass)  
> > &nbsp;&nbsp;&nbsp;&nbsp;pr = eval("proc do |\*args| #{s.to\_str} end", empty\_binding)  
> > &nbsp;&nbsp;&nbsp;&nbsp;pr[\*args\_to\_pass]  
> > end
> > 
> > eval\_string(\<\<EOL, [1, 2, 3, 4, 5])  
> > &nbsp;&nbsp;b = args.collect {|i| i\*3}  
> > &nbsp;&nbsp;c = b.join("||")  
> > &nbsp;&nbsp;puts(c)  
> > &nbsp;&nbsp;#p pr #\<-- now this fails  
> > EOL

Just one thing: why the use of 'proc do ... end ' rather than lambda? I know there's a difference, but I'm not sure what.

---

<div class="post-metadata">

**Author:** ![Joel\_VanderWerf1](https://avatars.discourse-cdn.com/v4/letter/j/94ad74/32.png) [@Joel\_VanderWerf1](https://rubytalk.org/u/Joel_VanderWerf1)\
**Post date:** [17 February 2005 21:54 UTC](https://rubytalk.org/t/evaluating-a-string-of-ruby-code-within-an-anonymous-module-done-correctly/16556/7 "2005-02-17T21:54:40Z")

</div>

Asfand Yar Qazi wrote:

> Asfand Yar Qazi wrote:
> 
> > > Just realized how to fix that:
> > > 
> > > def empty\_binding  
> > > &nbsp;&nbsp;binding  
> > > end
> > > 
> > > def eval\_string(s, \*args\_to\_pass)  
> > > &nbsp;&nbsp;&nbsp;&nbsp;pr = eval("proc do |\*args| #{s.to\_str} end", empty\_binding)  
> > > &nbsp;&nbsp;&nbsp;&nbsp;pr[\*args\_to\_pass]  
> > > end
> > > 
> > > eval\_string(\<\<EOL, [1, 2, 3, 4, 5])  
> > > &nbsp;&nbsp;b = args.collect {|i| i\*3}  
> > > &nbsp;&nbsp;c = b.join("||")  
> > > &nbsp;&nbsp;puts(c)  
> > > &nbsp;&nbsp;#p pr #\<-- now this fails  
> > > EOL
> 
> Just one thing: why the use of 'proc do ... end ' rather than lambda? I know there's a difference, but I'm not sure what.

AFAIK, lambda and proc are the same in ruby. But there may have been some talk about deprecating proc in the future.
