Block Passing and &foo Parameters

B

Brian McCallister

My understanding of the &parameter syntax is that it just wraps a
passed block in a proc:

irb(main):003:0> def one(&func)
irb(main):004:1> func.call
irb(main):005:1> end
=> nil
irb(main):006:0> one { puts 1 }
1
=> nil
irb(main):007:0>

What would break if we had the &param parameter actually act as a
declared parameter which must still be at the end:

irb(main):008:0> one(lambda {puts 1})
ArgumentError: wrong number of arguments (1 for 0)
from (irb):8:in `one'
from (irb):8
from :0
irb(main):009:0>

You can approximate this now with a default for the argument:

irb(main):011:0> def two(func = lambda { yield })
irb(main):012:1> func.call
irb(main):013:1> end
=> nil
irb(main):014:0> two { puts 1}
1
=> nil
irb(main):015:0> two(lambda { puts 2} )
2
=> nil
irb(main):016:0>

The advantage to something like this is if you have one function you
want to pass to a number of things, such as lists:

irb(main):016:0> a = [1,2,3]
=> [1, 2, 3]
irb(main):017:0> b = [4,5,6]
=> [4, 5, 6]
irb(main):018:0> func = lambda {|i| puts i}
=> #<Proc:0x0034b1b8@(irb):18>
irb(main):019:0> a.each func
ArgumentError: wrong number of arguments (1 for 0)
from (irb):19:in `each'
from (irb):19
from :0
irb(main):020:0> b.each func
ArgumentError: wrong number of arguments (1 for 0)
from (irb):20:in `each'
from (irb):20
from :0
irb(main):021:0>

You can add this now via:

irb(main):031:0> class Array
irb(main):032:1> alias old_each each
irb(main):033:1> def each(func = lambda {|i| yield i})
irb(main):034:2> old_each {|i| func.call i}
irb(main):035:2> end
irb(main):036:1> end
=> nil
irb(main):037:0> [1,2,3].each func
1
2
3
=> [1, 2, 3]
irb(main):038:0>

What would break if a special case allowed for passing of a Proc in the
place of &param in place of passing in a block?

-Brian
 
A

Assaph Mehr

The advantage to something like this is if you have one function you
want to pass to a number of things, such as lists:

irb(main):016:0> a = [1,2,3]
=> [1, 2, 3]
irb(main):017:0> b = [4,5,6]
=> [4, 5, 6]
irb(main):018:0> func = lambda {|i| puts i}
=> #<Proc:0x0034b1b8@(irb):18>
irb(main):019:0> a.each func
ArgumentError: wrong number of arguments (1 for 0)
from (irb):19:in `each'
from (irb):19
from :0
irb(main):020:0> b.each func

You can easily pass a lambda to somethig that expects a block - just
put another & before lambda param at the point of call:

irb(main):001:0> a = [1,2,3]
=> [1, 2, 3]
irb(main):002:0> b = [4,5,6]
=> [4, 5, 6]
irb(main):003:0> func = lambda{|i| puts i}
=> #<Proc:0x02c2d6d0@(irb):3>
irb(main):004:0> a.each &func
1
2
3
=> [1, 2, 3]
 
B

Brian McCallister

Ah hah! Thanks, I knew this had to be way too common to not have been
handled. Thank you!

-Brian

The advantage to something like this is if you have one function you
want to pass to a number of things, such as lists:

irb(main):016:0> a = [1,2,3]
=> [1, 2, 3]
irb(main):017:0> b = [4,5,6]
=> [4, 5, 6]
irb(main):018:0> func = lambda {|i| puts i}
=> #<Proc:0x0034b1b8@(irb):18>
irb(main):019:0> a.each func
ArgumentError: wrong number of arguments (1 for 0)
from (irb):19:in `each'
from (irb):19
from :0
irb(main):020:0> b.each func

You can easily pass a lambda to somethig that expects a block - just
put another & before lambda param at the point of call:

irb(main):001:0> a = [1,2,3]
=> [1, 2, 3]
irb(main):002:0> b = [4,5,6]
=> [4, 5, 6]
irb(main):003:0> func = lambda{|i| puts i}
=> #<Proc:0x02c2d6d0@(irb):3>
irb(main):004:0> a.each &func
1
2
3
=> [1, 2, 3]
 

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

Staff online

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,118
Latest member
LatishaWhy
Top