A cleaner way to pass a block or proc

Discussion in 'Ruby' started by Tristin Davis, Jun 26, 2008.

  1. [Note: parts of this message were removed to make it a legal post.]

    Is there a cleaner way to implement my add_notifier method?

    def add_notifier(notifier, &block)
    if block_given?
    @notifiers << block
    else
    @notifiers << notifier
    end
    end

    def thump
    raise ArgumentError, "You must add_notifier before you can notify" if
    @notifiers.empty?
    @notifiers.each {|n| n.call }
    end


    Here's how the method will be used.

    hb.add_notifier nil do
    puts "Notification1"
    end

    meth = lambda{ puts "notification2" }
    hb.add_notifier(meth)

    It just seems really unpretty to pass that nil when I want to pass just the
    block.
     
    Tristin Davis, Jun 26, 2008
    #1
    1. Advertising

  2. Tristin Davis

    ara.t.howard Guest

    On Jun 25, 2008, at 5:48 PM, Tristin Davis wrote:

    > def add_notifier(notifier, &block)
    > if block_given?
    > @notifiers << block
    > else
    > @notifiers << notifier
    > end
    > end



    def add_notifier *argv, &block
    argv.push block
    @notifiers.push *argv
    end


    a @ http://codeforpeople.com/
    --
    we can deny everything, except that we have the possibility of being
    better. simply reflect on that.
    h.h. the 14th dalai lama
     
    ara.t.howard, Jun 26, 2008
    #2
    1. Advertising

  3. On Thu, Jun 26, 2008, Tristin Davis wrote:
    > It just seems really unpretty to pass that nil when I want to pass just the
    > block.


    As an alternative to Ara's suggestion:

    def add_notifier( notifier = nil, &block )

    You'll need to change some of your internal logic as well to deal with
    notifier being nil sometimes, but I like this better than using splats.
    Personal taste.

    Ben
     
    Ben Bleything, Jun 26, 2008
    #3
  4. [Note: parts of this message were removed to make it a legal post.]

    Thanks Ben. That worked perfect. No other changes required in the class. :)

    Here's the final code. Maybe someone can get some use out of it. It sends a
    heartbeat (of your choosing) from your running ruby app at a given interval.

    class HeartBeat

    attr_accessor :interval

    def initialize(interval=120)
    @interval = interval
    @notifiers = Array.new
    end

    def add_notifier(notifier=nil, &block)
    if block_given?
    @notifiers << block
    else
    @notifiers << notifier
    end
    end

    def thump
    raise ArgumentError, "You must add_notifier before you can notify" if
    @notifiers.empty?
    @notifiers.each {|n| n.call }
    end

    def start
    Thread.abort_on_exception = true
    @thread = Thread.new do
    while true
    thump
    sleep @interval
    end
    end
    end

    def stop
    @thread.terminate
    end
    end

    On Wed, Jun 25, 2008 at 7:05 PM, Ben Bleything <> wrote:

    > On Thu, Jun 26, 2008, Tristin Davis wrote:
    > > It just seems really unpretty to pass that nil when I want to pass just

    > the
    > > block.

    >
    > As an alternative to Ara's suggestion:
    >
    > def add_notifier( notifier = nil, &block )
    >
    > You'll need to change some of your internal logic as well to deal with
    > notifier being nil sometimes, but I like this better than using splats.
    > Personal taste.
    >
    > Ben
    >
    >
     
    Tristin Davis, Jun 26, 2008
    #4
  5. Tristin Davis wrote:
    > def add_notifier(notifier=nil, &block)
    > if block_given?
    > @notifiers << block
    > else
    > @notifiers << notifier
    > end
    > end


    def add_notifier(notifier=nil, &block)
    @notifiers << (block || notifier)
    end

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
     
    Joel VanderWerf, Jun 26, 2008
    #5
  6. On Thu, Jun 26, 2008 at 3:04 AM, Joel VanderWerf
    <> wrote:
    > Tristin Davis wrote:
    >>
    >> def add_notifier(notifier=nil, &block)
    >> if block_given?
    >> @notifiers << block
    >> else
    >> @notifiers << notifier
    >> end
    >> end

    >
    > def add_notifier(notifier=nil, &block)
    > @notifiers << (block || notifier)
    > end


    I think you could end up adding some nils with
    this solution and the previous one, if I call:

    Heartbeat.new.add_notifier

    without any argument or block. Maybe you will
    want to check it in the add_notifier method, or
    at least handle it in the thump method, to avoid
    calling the call method on nil. Maybe something like:

    def add_notifier(notifier=nil, &block)
    raise "Both nil" unless (notifier || block)
    @notifiers << (block || notifier)
    end

    Jesus.
     
    Jesús Gabriel y Galán, Jun 26, 2008
    #6
  7. Tristin Davis

    Robert Dober Guest

    On Thu, Jun 26, 2008 at 3:04 AM, Joel VanderWerf
    <> wrote:
    > Tristin Davis wrote:
    >>
    >> def add_notifier(notifier=3Dnil, &block)
    >> if block_given?
    >> @notifiers << block
    >> else
    >> @notifiers << notifier
    >> end
    >> end

    >
    > def add_notifier(notifier=3Dnil, &block)
    > @notifiers << (block || notifier)
    > end


    I would do it exactly as J=F6el suggested above, however there is an
    interesting alternative one might want to be aware of

    def add_notfier notifier=3Dnil
    @notifiers << ( Proc::new rescue notifier)
    end

    Cheers
    Robert


    --=20
    http://ruby-smalltalk.blogspot.com/

    ---
    Les m=EAmes questions qu'on se pose
    On part vers o=F9 et vers qui
    Et comme indice pas grand-chose
    Des roses et des orties.
    -
    Francis Cabrel
     
    Robert Dober, Jun 26, 2008
    #7
  8. Tristin Davis

    ara.t.howard Guest

    On Jun 26, 2008, at 4:39 AM, Robert Dober wrote:

    > def add_notfier notifier=nil
    > @notifiers << ( Proc::new rescue notifier)
    > end


    still adds nil if no args given though...


    cheers.

    a @ http://codeforpeople.com/
    --
    we can deny everything, except that we have the possibility of being
    better. simply reflect on that.
    h.h. the 14th dalai lama
     
    ara.t.howard, Jun 26, 2008
    #8
  9. On Thu, Jun 26, 2008, Jess Gabriel y Galn wrote:
    > I think you could end up adding some nils with
    > this solution and the previous one, if I call:
    >
    > Heartbeat.new.add_notifier
    >
    > without any argument or block.


    Right, this is why I suggested modifying the block to handle the nils :)

    Ben
     
    Ben Bleything, Jun 26, 2008
    #9
  10. [Note: parts of this message were removed to make it a legal post.]

    The final result.

    def add_notifier(notifier=nil, &block)
    raise ArgumentError, "Nil notifier. You must provide a Proc or a
    block" if notifier.nil? && block.nil?
    @notifiers << (notifier || block)
    end

    On Thu, Jun 26, 2008 at 10:19 AM, Ben Bleything <> wrote:

    > On Thu, Jun 26, 2008, Jess Gabriel y Galn wrote:
    > > I think you could end up adding some nils with
    > > this solution and the previous one, if I call:
    > >
    > > Heartbeat.new.add_notifier
    > >
    > > without any argument or block.

    >
    > Right, this is why I suggested modifying the block to handle the nils :)
    >
    > Ben
    >
    >
     
    Tristin Davis, Jun 26, 2008
    #10
  11. Tristin Davis

    Robert Dober Guest

    On Thu, Jun 26, 2008 at 4:27 PM, ara.t.howard <> wrote:
    >
    > On Jun 26, 2008, at 4:39 AM, Robert Dober wrote:
    >
    >> def add_notfier notifier=nil
    >> @notifiers << ( Proc::new rescue notifier)
    >> end

    >
    > still adds nil if no args given though...
    >
    >
    > cheers.
    >
    > a @ http://codeforpeople.com/
    > --
    > we can deny everything, except that we have the possibility of being better.
    > simply reflect on that.
    > h.h. the 14th dalai lama
    >

    That is what OP wanted IIANM, the nils raise an exception later on.
    Anyway I thought I had made it clear that your code is preferable but
    I feel that teaching what Proc::new is about, is part of our job here
    ;)

    Cheers
    Robert
     
    Robert Dober, Jun 26, 2008
    #11
  12. [Note: parts of this message were removed to make it a legal post.]

    Can you explain it to me?

    @notifiers << ( Proc::new rescue notifier)

    On Thu, Jun 26, 2008 at 1:44 PM, Robert Dober <>
    wrote:

    > On Thu, Jun 26, 2008 at 4:27 PM, ara.t.howard <>
    > wrote:
    > >
    > > On Jun 26, 2008, at 4:39 AM, Robert Dober wrote:
    > >
    > >> def add_notfier notifier=nil
    > >> @notifiers << ( Proc::new rescue notifier)
    > >> end

    > >
    > > still adds nil if no args given though...
    > >
    > >
    > > cheers.
    > >
    > > a @ http://codeforpeople.com/
    > > --
    > > we can deny everything, except that we have the possibility of being

    > better.
    > > simply reflect on that.
    > > h.h. the 14th dalai lama
    > >

    > That is what OP wanted IIANM, the nils raise an exception later on.
    > Anyway I thought I had made it clear that your code is preferable but
    > I feel that teaching what Proc::new is about, is part of our job here
    > ;)
    >
    > Cheers
    > Robert
    >
    >
     
    Tristin Davis, Jun 26, 2008
    #12
  13. Tristin Davis

    ara.t.howard Guest

    On Jun 26, 2008, at 12:44 PM, Robert Dober wrote:

    > That is what OP wanted IIANM, the nils raise an exception later on.
    > Anyway I thought I had made it clear that your code is preferable but
    > I feel that teaching what Proc::new is about, is part of our job here
    > ;)



    ah. btw - i did not know about the argumentless Proc::new so you
    achieved your goal ;-)

    a @ http://codeforpeople.com/
    --
    we can deny everything, except that we have the possibility of being
    better. simply reflect on that.
    h.h. the 14th dalai lama
     
    ara.t.howard, Jun 26, 2008
    #13
  14. Tristin Davis

    Robert Dober Guest

    On Thu, Jun 26, 2008 at 9:18 PM, ara.t.howard <> wrote:
    >
    > On Jun 26, 2008, at 12:44 PM, Robert Dober wrote:
    >
    >> That is what OP wanted IIANM, the nils raise an exception later on.
    >> Anyway I thought I had made it clear that your code is preferable but
    >> I feel that teaching what Proc::new is about, is part of our job here
    >> ;)

    >
    >
    > ah. btw - i did not know about the argumentless Proc::new so you achieved
    > your goal ;-)
    >
    > a @ http://codeforpeople.com/
    > --
    > we can deny everything, except that we have the possibility of being better.
    > simply reflect on that.
    > h.h. the 14th dalai lama
    >
    >
    >
    >
    >



    Great I will spell it out for OP

    Block::new takes implicitely the block you have passed to a method

    irb(main):001:0> def a
    irb(main):002:1> Proc::new.call
    irb(main):003:1> end
    => nil
    irb(main):004:0> a do 42 end
    => 42


    However if there was no block passed to the method there will be an error
    irb(main):005:0> a
    ArgumentError: tried to create Proc object without a block
    from (irb):2:in `new'
    from (irb):2:in `a'

    This error was caught by my rescue clause in the line

    @notifiers << ( Proc::new rescue notifier )


    But please again, Ara's code is better idiomatic Ruby, but just in
    case you stumble around Proc::new one day ;)

    HTH
    Robert
    --
    http://ruby-smalltalk.blogspot.com/

    ---
    AALST (n.) One who changes his name to be further to the front
    D.Adams; The Meaning of LIFF
     
    Robert Dober, Jun 26, 2008
    #14
  15. Tristin Davis wrote:
    > def add_notifier(notifier=nil, &block)
    > raise ArgumentError, "Nil notifier. You must provide a Proc or a
    > block" if notifier.nil? && block.nil?
    > @notifiers << (notifier || block)
    > end


    A little less redundant...

    def add_notifier(notifier=nil, &block)
    @notifiers << (notifier || block || (
    raise ArgumentError,
    "Nil notifier. You must provide a Proc or a block"
    ))
    end

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
     
    Joel VanderWerf, Jun 26, 2008
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. David Lozzi
    Replies:
    3
    Views:
    1,997
    David Lozzi
    Jun 1, 2005
  2. NevilleDNZ
    Replies:
    9
    Views:
    463
    NevilleDNZ
    Aug 16, 2006
  3. Jean-Hugues ROBERT

    Why no Proc##[]=() ? Why no Proc##replace() ?

    Jean-Hugues ROBERT, May 1, 2004, in forum: Ruby
    Replies:
    14
    Views:
    316
    Jean-Hugues ROBERT
    May 5, 2004
  4. Wolfgang Nádasi-Donner
    Replies:
    0
    Views:
    141
    Wolfgang Nádasi-Donner
    May 31, 2007
  5. makoto kuwata
    Replies:
    1
    Views:
    656
    Robert Klemme
    Apr 22, 2012
Loading...

Share This Page