# "once" meta-method without "module\_eval" (Pickaxe)

**URL:** <https://rubytalk.org/t/once-meta-method-without-module-eval-pickaxe/42191>\
**Category:** ruby-talk\
**Created:** [14 November 2007 06:23 UTC](https://rubytalk.org/t/once-meta-method-without-module-eval-pickaxe/42191 "2007-11-14T06:23:35Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Greg\_Weeks](https://avatars.discourse-cdn.com/v4/letter/g/85f322/32.png) [@Greg\_Weeks](https://rubytalk.org/u/Greg_Weeks)\
**Post date:** [14 November 2007 06:23 UTC](https://rubytalk.org/t/once-meta-method-without-module-eval-pickaxe/42191/1 "2007-11-14T06:23:35Z")

</div>

My impression is that Ruby meta-programming used to lean heavily on  
evaluating strings as code, but is moving away from that. (Good!) In  
that spirit, it would be nice to replace this example from Chapter 24,  
Classes and Objects:

class Date  
&nbsp;&nbsp;class \<\<self  
&nbsp;&nbsp;&nbsp;&nbsp;def once(\*ids) # :nodoc:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for id in ids  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module\_eval \<\<-"end;"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alias\_method :\_\_#{id.to\_i}\_\_, :#{id.to\_s}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private :\_\_#{id.to\_i}\_\_  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def #{id.to\_s}(\*args, &block)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(@\_\_#{id.to\_i}\_\_ ||= [\_\_#{id.to\_i}\_\_(\*args, &block)])[0]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end  
&nbsp;&nbsp;...  
&nbsp;&nbsp;once :as\_string, :as\_YMD  
end

"once" replaces a specified method with a method that caches the return  
value on the first call.

The example above served to illustrate the use of class instance  
variables. However, the replacement that comes to mind does not:

&nbsp;&nbsp;class \<\<self  
&nbsp;&nbsp;&nbsp;&nbsp;def once(\*ids)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;values = {}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for id in ids  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new\_id = "\_\_#{id.to\_i}\_\_".to\_sym  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alias\_method new\_id, id  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private new\_id  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;define\_method (id) do |\*args|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(values[id] ||= [method(new\_id).call(\*args)])[0]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end

Is there some way to avoid evals and still use class instance variables?

Is there some way to avoid evals and still handle the "&block" argument?

Is there a natural alternative to the local hash variable?

Am I right to think that eval-ing strings is retro?

(By the way, neither implementation allows "once" to be called twice  
with the same symbol.)

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![7rans](https://avatars.discourse-cdn.com/v4/letter/7/a8b319/32.png) [@7rans](https://rubytalk.org/u/7rans)\
**Post date:** [14 November 2007 11:45 UTC](https://rubytalk.org/t/once-meta-method-without-module-eval-pickaxe/42191/2 "2007-11-14T11:45:34Z")

</div>

> My impression is that Ruby meta-programming used to lean heavily on  
> evaluating strings as code, but is moving away from that. (Good!) In  
> that spirit, it would be nice to replace this example from Chapter 24,  
> Classes and Objects:
> 
> class Date  
> &nbsp;&nbsp;class \<\<self  
> &nbsp;&nbsp;&nbsp;&nbsp;def once(\*ids) # :nodoc:  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for id in ids  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module\_eval \<\<-"end;"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alias\_method :\_\_#{id.to\_i}\_\_, :#{id.to\_s}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private :\_\_#{id.to\_i}\_\_  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def #{id.to\_s}(\*args, &block)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(@\_\_#{id.to\_i}\_\_ ||= [\_\_#{id.to\_i}\_\_(\*args, &block)])[0]  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;end  
> &nbsp;&nbsp;...  
> &nbsp;&nbsp;once :as\_string, :as\_YMD  
> end
> 
> "once" replaces a specified method with a method that caches the return  
> value on the first call.
> 
> The example above served to illustrate the use of class instance  
> variables. However, the replacement that comes to mind does not:
> 
> &nbsp;&nbsp;class \<\<self  
> &nbsp;&nbsp;&nbsp;&nbsp;def once(\*ids)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;values = {}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for id in ids  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new\_id = "\_\_#{id.to\_i}\_\_".to\_sym  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alias\_method new\_id, id  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private new\_id  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;define\_method (id) do |\*args|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(values[id] ||= [method(new\_id).call(\*args)])[0]  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;end
> 
> Is there some way to avoid evals and still use class instance variables?

instance\_variable\_get/set

> Is there some way to avoid evals and still handle the "&block" argument?

Wait for 1.9.

> Is there a natural alternative to the local hash variable?

instance\_variable\_get/set if you want to do it like the original, but  
your local might be better.

> Am I right to think that eval-ing strings is retro?

I'm not sure there's anything really wrong with eval. Often the code  
looks cleaner compared to these long winded meta-methods.

T.

> **···**
>
> On Nov 14, 1:23 am, Greg Weeks \<greg.we...@arm.com\> wrote:

---

<div class="post-metadata">

**Author:** ![Daniel\_DeLorme](https://avatars.discourse-cdn.com/v4/letter/d/9d8465/32.png) [@Daniel\_DeLorme](https://rubytalk.org/u/Daniel_DeLorme)\
**Post date:** [14 November 2007 12:24 UTC](https://rubytalk.org/t/once-meta-method-without-module-eval-pickaxe/42191/3 "2007-11-14T12:24:20Z")

</div>

Greg Weeks wrote:

> My impression is that Ruby meta-programming used to lean heavily on  
> evaluating strings as code, but is moving away from that. (Good!)

I have just one question: why is that good? Is it just that avoiding evaluation of strings somehow "feels cleaner" or is there actually a justification for that?

If you rememer that load/require basically has the effect of eval'ing the content of a file, string eval doesn't feel so evil anymore.

Daniel

---

<div class="post-metadata">

**Author:** ![Gavin\_Kistner3](https://avatars.discourse-cdn.com/v4/letter/g/dfb087/32.png) [@Gavin\_Kistner3](https://rubytalk.org/u/Gavin_Kistner3)\
**Post date:** [14 November 2007 20:10 UTC](https://rubytalk.org/t/once-meta-method-without-module-eval-pickaxe/42191/4 "2007-11-14T20:10:13Z")

</div>

My first dynamically-typed, runtime-interpreted scripting language was  
JavaScript. In JavaScript, eval is considered a bad idea. Loading a  
string of JavaScript code compiles it to bytecode and then executes  
the byte code. Hitting an eval() call in the middle of a program  
requires booting up the lexer and bytecode compiler again, to handle  
that one string, before it can be run. It's inefficient, and almost  
never needed.

I gather the same is not true in Ruby currently. I think (but may be  
horribly wrong) that this is not so much because of some excellent  
implementation of eval, but a because everything is in the same slow  
pool of interpretation.

I'm totally guessing, but I would suspect that at some point in Ruby's  
runtime future, startup optimizations/compilations will happen once  
only. If this is true (and I know very little about virtual machines  
and bytecodes and the actual implementation, so I could be wrong),  
then I would suspect that eval of a string (not a block) will incur  
undesirable overhead.

For these reasons (my history with eval in JS and my suspicion that it  
may become undesirable from a performance standpoint) I personally  
never eval strings.

> **···**
>
> On Nov 13, 11:23 pm, Greg Weeks \<greg.we...@arm.com\> wrote:
> 
> > Am I right to think that eval-ing strings is retro?

---

<div class="post-metadata">

**Author:** ![a11](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/a11/32/8169_2.png) [@a11](https://rubytalk.org/u/a11)\
**Post date:** [14 November 2007 17:37 UTC](https://rubytalk.org/t/once-meta-method-without-module-eval-pickaxe/42191/5 "2007-11-14T17:37:43Z")

</div>

not to mention it doesn't create a closure/leak...

a @ [http://codeforpeople.com/](http://codeforpeople.com/)

> **···**
>
> On Nov 14, 2007, at 5:24 AM, Daniel DeLorme wrote:
> 
> > If you rememer that load/require basically has the effect of eval'ing the content of a file, string eval doesn't feel so evil anymore.
> 
> --  
> share your knowledge. it's a way to achieve immortality.  
> h.h. the 14th dalai lama

---

<div class="post-metadata">

**Author:** ![7rans](https://avatars.discourse-cdn.com/v4/letter/7/a8b319/32.png) [@7rans](https://rubytalk.org/u/7rans)\
**Post date:** [14 November 2007 18:07 UTC](https://rubytalk.org/t/once-meta-method-without-module-eval-pickaxe/42191/6 "2007-11-14T18:07:19Z")

</div>

another good point! and i still think there should be a way to shut  
out the closure for a block.

T.

> **···**
>
> On Nov 14, 12:37 pm, "ara.t.howard" \<ara.t.how...@gmail.com\> wrote:
> 
> > On Nov 14, 2007, at 5:24 AM, Daniel DeLorme wrote:
> > 
> > \> If you rememer that load/require basically has the effect of  
> > \> eval'ing the content of a file, string eval doesn't feel so evil  
> > \> anymore.
> > 
> > not to mention it doesn't create a closure/leak...

---

<div class="post-metadata">

**Author:** ![Greg\_Weeks](https://avatars.discourse-cdn.com/v4/letter/g/85f322/32.png) [@Greg\_Weeks](https://rubytalk.org/u/Greg_Weeks)\
**Post date:** [14 November 2007 19:39 UTC](https://rubytalk.org/t/once-meta-method-without-module-eval-pickaxe/42191/7 "2007-11-14T19:39:25Z")

</div>

First, thanks (you all) for the info I asked for.

> \> Am I right to think that eval-ing strings is retro?
> 
> I'm not sure there's anything really wrong with eval. Often the code  
> looks cleaner compared to these long winded meta-methods.

My intuition is that a good argument could be given. But I'm not the  
person to give it.

> not to mention it doesn't create a closure/leak...

The fact that I can use "define-method" to \*almost but not quite\*  
achieve the affect of a "def" is almost certainly a Ruby wart. If I run  
into trouble I'll just blame Matz 🙂

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).
