# Once modifier (pickaxe book page 391)

**URL:** <https://www.ruby-forum.com/t/once-modifier-pickaxe-book-page-391/92571>\
**Category:** Ruby\
**Created:** [April 20, 2007, 9:10pm UTC](https://www.ruby-forum.com/t/once-modifier-pickaxe-book-page-391/92571 "2007-04-20T21:10:49Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![ChrisKaelin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/b2d939/32.png) [@ChrisKaelin](https://www.ruby-forum.com/u/ChrisKaelin)\
**Post date:** [April 20, 2007, 9:10pm UTC](https://www.ruby-forum.com/t/once-modifier-pickaxe-book-page-391/92571/1 "2007-04-20T21:10:49Z")

</div>

The following code is from the pickaxe book page 391 (slightly  
modified in order to have it available in all classes, that are  
defined). It implements a once modifier, that ensures a method’s body  
is only called, if it’s return value (an instance variable) is not  
already set.

# Extending Module with the amazing once modifier

class Module  
def once(\*ids) # :nodoc:  
for id in ids  
module\_eval \<\<-“EOF”  
alias\_method : **#{id.to\_i}** , :#{id.to\_s}  
private\_methods : **#{id.to\_i}**  
def #{id.to\_s}(\*args, &block)  
(@ **#{id.to\_i}** ||= [**#{id.to\_i}** (\*args, &block)])[0]  
end  
EOF  
end  
end  
end

It really works very well and is a wonderful example of ruby’s power.

But I got some noob questions now:

- Why isn’t this cool method available in ruby directly?
- Why can’t I use “ids.each” instead of “for id in ids”? Ok, this  
question has nothing to do with the code itself 😉
- I know what “||=” does (evaluate assignment only, if the left part  
is false), but what do you call this?

Sorry for my lack of these basics and thanks in advance for any  
answers.

Chris

---

<div class="post-metadata">

**Author:** ![ChrisKaelin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/b2d939/32.png) [@ChrisKaelin](https://www.ruby-forum.com/u/ChrisKaelin)\
**Post date:** [April 20, 2007, 9:20pm UTC](https://www.ruby-forum.com/t/once-modifier-pickaxe-book-page-391/92571/2 "2007-04-20T21:20:53Z")

</div>

On Sat, 21 Apr 2007, ChrisKaelin wrote:

> ```
> module_eval <<-"EOF"
> 
> ```
> 
> It really works very well and is a wonderful example of ruby’s power.
> 
> But I got some noob questions now:
> 
> - Why isn’t this cool method available in ruby directly?

one possible reason

harp:~ \> cat a.rb  
require ‘once’  
class NotRobust  
def foo() p 42 end  
once :foo  
end

nr = NotRobust.new  
2.times{ nr.foo }

harp:~ \> ruby a.rb  
42

harp:~ \> cat a.rb  
require ‘once’  
class NotRobust  
def foo() p 42 end  
2.times{ once :foo }  
end

nr = NotRobust.new  
2.times{ nr.foo }

harp:~ \> ruby a.rb  
Segmentation fault (core dumped)

harp:~ \> ruby --version  
ruby 1.8.4 (2005-12-01) [i686-linux]

regards.

-a

---

<div class="post-metadata">

**Author:** ![ChrisKaelin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/b2d939/32.png) [@ChrisKaelin](https://www.ruby-forum.com/u/ChrisKaelin)\
**Post date:** [April 20, 2007, 9:30pm UTC](https://www.ruby-forum.com/t/once-modifier-pickaxe-book-page-391/92571/3 "2007-04-20T21:30:54Z")

</div>

removed\_email\_address@domain.invalid wrote:

> nr = NotRobust.new  
> class NotRobust
> 
> harp:~ \> ruby --version  
> ruby 1.8.4 (2005-12-01) [i686-linux]
> 
> regards.
> 
> -a  
> whoops, o.k. I see…  
> but… why should I do this: 2.times { once :foo } ? o.k. I can  
> imagine, ruby should allow everything without coredumping 😉

---

<div class="post-metadata">

**Author:** ![ChrisKaelin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/b2d939/32.png) [@ChrisKaelin](https://www.ruby-forum.com/u/ChrisKaelin)\
**Post date:** [April 20, 2007, 10:06pm UTC](https://www.ruby-forum.com/t/once-modifier-pickaxe-book-page-391/92571/4 "2007-04-20T22:06:02Z")

</div>

On Sat, 21 Apr 2007, ChrisKaelin wrote:

> > ```
> > once :foo
> > 
> > ```
> 
> whoops, o.k. I see…  
> but… why should I do this: 2.times { once :foo } ? o.k. I can  
> imagine, ruby should allow everything without coredumping 😉

-a

---

<div class="post-metadata">

**Author:** ![ChrisKaelin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/b2d939/32.png) [@ChrisKaelin](https://www.ruby-forum.com/u/ChrisKaelin)\
**Post date:** [April 20, 2007, 10:25pm UTC](https://www.ruby-forum.com/t/once-modifier-pickaxe-book-page-391/92571/5 "2007-04-20T22:25:04Z")

</div>

On Sat, Apr 21, 2007 at 04:10:09AM +0900, ChrisKaelin wrote:

> - Why can’t I use “ids.each” instead of “for id in ids”? Ok, this  
> question has nothing to do with the code itself 😉

ids.each do |id|  
…  
end

> - I know what “||=” does (evaluate assignment only, if the left part  
> is false), but what do you call this?

Note that

a ||= b

is syntactic sugar for

a = a || b

My K&R C book just calls them “assignment operators”, although C doesn’t  
have ||= (but it has \*=, /=, %=, +=, -=, \<\<=. \>\>=, &=, ^=, |=)

---

<div class="post-metadata">

**Author:** ![ChrisKaelin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/b2d939/32.png) [@ChrisKaelin](https://www.ruby-forum.com/u/ChrisKaelin)\
**Post date:** [April 21, 2007, 9:46am UTC](https://www.ruby-forum.com/t/once-modifier-pickaxe-book-page-391/92571/6 "2007-04-21T09:46:44Z")

</div>

ChrisKaelin wrote:

> SyntaxError: compile error  
> (irb):3: syntax error, unexpected kDO  
> (irb):13: can’t find string “EOF” anywhere before EOF

That would be caused by leaving out the “EOF” not by replacing  
the for-loop with each.

HTH,  
Sebastian H.

---

<div class="post-metadata">

**Author:** ![ChrisKaelin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/b2d939/32.png) [@ChrisKaelin](https://www.ruby-forum.com/u/ChrisKaelin)\
**Post date:** [April 21, 2007, 12:31am UTC](https://www.ruby-forum.com/t/once-modifier-pickaxe-book-page-391/92571/7 "2007-04-21T00:31:14Z")

</div>

On 20 Apr., 22:24, Brian C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> On Sat, Apr 21, 2007 at 04:10:09AM +0900, ChrisKaelin wrote:
> 
> > - Why can’t I use “ids.each” instead of “for id in ids”? Ok, this  
> > question has nothing to do with the code itself 😉
> 
> ids.each do |id|  
> …  
> end  
> nope, that gives me:  
> SyntaxError: compile error  
> (irb):3: syntax error, unexpected kDO  
> (irb):13: can’t find string “EOF” anywhere before EOF  
> (irb):4: syntax error, unexpected $end, expecting tSTRING\_CONTENT or  
> tSTRING\_DBEG or tSTRING\_DVAR or tSTRING\_END  
> from (irb):4  
> from :0

while " for id in ids" works well (that’s why the official code uses  
it, I guess. Normally “each” is preferred over that, afaik.

> My K&R C book just calls them “assignment operators”, although C doesn’t  
> have ||= (but it has \*=, /=, %=, +=, -=, \<\<=. \>\>=, &=, ^=, |=)  
> my fault, I should’ve known that, I just only knew ||= from Array  
> stuff, so I could not get the link to a = a || b. Thanks a lot!

---

<div class="post-metadata">

**Author:** ![ChrisKaelin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/b2d939/32.png) [@ChrisKaelin](https://www.ruby-forum.com/u/ChrisKaelin)\
**Post date:** [April 22, 2007, 8:25pm UTC](https://www.ruby-forum.com/t/once-modifier-pickaxe-book-page-391/92571/8 "2007-04-22T20:25:31Z")

</div>

On 21 Apr., 09:46, Sebastian H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> ChrisKaelin wrote:
> 
> > SyntaxError: compile error  
> > (irb):3: syntax error, unexpected kDO  
> > (irb):13: can’t find string “EOF” anywhere before EOF
> 
> That would be caused by leaving out the “EOF” not by replacing  
> the for-loop with each.  
> Even more shame for me:  
> it was, because I used  
> ids.each |id| do  
> instead of  
> ids.each do |id|

ouch!
