A cleaner way to pass a block or proc

T

Tristin Davis

[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.
 
B

Ben Bleything

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
 
T

Tristin Davis

[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
 
J

Joel VanderWerf

Tristin said:
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
 
J

Jesús Gabriel y Galán

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.
 
R

Robert Dober

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
 
B

Ben Bleything

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
 
T

Tristin Davis

[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
 
R

Robert Dober

still adds nil if no args given though...


cheers.

a @ http://codeforpeople.com/
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
 
T

Tristin Davis

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

Can you explain it to me?

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

ara.t.howard

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/
 
R

Robert Dober

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

a @ http://codeforpeople.com/


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
 
J

Joel VanderWerf

Tristin said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top