Forum: Ruby once modifier (pickaxe book page 391)

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
084b13bebff6514ac50cd171c4e10e51?d=identicon&s=25 ChrisKaelin (Guest)
on 2007-04-20 21:10
(Received via mailing list)
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
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 unknown (Guest)
on 2007-04-20 21:20
(Received via mailing list)
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
084b13bebff6514ac50cd171c4e10e51?d=identicon&s=25 ChrisKaelin (Guest)
on 2007-04-20 21:30
(Received via mailing list)
ara.t.how...@noaa.gov 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 ;-)
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 unknown (Guest)
on 2007-04-20 22:06
(Received via mailing list)
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
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (Guest)
on 2007-04-20 22:25
(Received via mailing list)
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 *=, /=, %=, +=, -=, <<=. >>=, &=, ^=, |=)
084b13bebff6514ac50cd171c4e10e51?d=identicon&s=25 ChrisKaelin (Guest)
on 2007-04-21 00:31
(Received via mailing list)
On 20 Apr., 22:24, Brian Candler <B.Cand...@pobox.com> 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!
7a561ec0875fcbbe3066ea8fe288ec77?d=identicon&s=25 Sebastian Hungerecker (Guest)
on 2007-04-21 09:46
(Received via mailing list)
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 Hungerecker
084b13bebff6514ac50cd171c4e10e51?d=identicon&s=25 ChrisKaelin (Guest)
on 2007-04-22 20:25
(Received via mailing list)
On 21 Apr., 09:46, Sebastian Hungerecker <sep...@googlemail.com>
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!
This topic is locked and can not be replied to.