when it comes the method needs two block to accomplish a task,how the
ruby
do which? for example , the classical sum(filter,mapping,iterator)(I
have
forgotten the style, maybe,the one can search it in SICP)
gaoxtwarrior wrote:
when it comes the method needs two block to accomplish a task,how the ruby
do which? for example , the classical sum(filter,mapping,iterator)(I have
forgotten the style, maybe,the one can search it in SICP)
If the two blocks are applied sequentially, as part of two separate
iterations, it’s straightforward:
[1,2,“fred”,“wilma”,5,6].select{|x|x.kind_of?(Numeric)}.inject{|s,x|s+x}
=> 14
In this special case, we can use #grep because testing for
x.kind_of?(Numeric) is the same as testing Numeric === x (which is what
grep(Numeric) does):
[1,2,“fred”,“wilma”,5,6].grep(Numeric).inject{|s,x|s+x}
=> 14
More generally, though, the only way to pass more than one block to a
method is to turn all but one of the blocks into procs, like this:
meth_with_two_blocks(proc {…}) { … }
On 06.04.2007 07:11, gaoxtwarrior wrote:
when it comes the method needs two block to accomplish a task,how the ruby
do which? for example , the classical sum(filter,mapping,iterator)(I have
forgotten the style, maybe,the one can search it in SICP)
A straightforward way would be
irb(main):001:0> num=(1…10).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
irb(main):002:0> num.select {|x| x<5}.inject(0) {|sum,x| sum+x}
=> 10
irb(main):003:0> num.select {|x| x<5}.inject(0) {|sum,x| sum+(x3)}
=> 30
irb(main):012:0> num.select {|x| x<5}.map {|x| x3}.inject(0) {|sum,x|
sum+x}
=> 30
You don’t need the “iterator” argument because you typically define
these methods in Enumerable.
Other than that you can of course combine filter and mapping by mapping
values that are not included in the filter to 0:
irb(main):004:0> num.inject(0) {|sum,x| sum+(x < 5 ? x*3 : 0)}
=> 30
As has been pointed out, if you want to define a method “sum” that
accepts a filter and a mapping, you would have to provide at least one
of the two blocks via proc / lambda.
HTH
robert
On Apr 6, 1:15 am, “gaoxtwarrior” [email protected] wrote:
when it comes the method needs two block to accomplish a task,how the ruby
do which? for example , the classical sum(filter,mapping,iterator)(I have
forgotten the style, maybe,the one can search it in SICP)
You can cache one block and wait on the other, from another method,
eg.
foo{ block1 }.bar{ block2 }
Like so:
def foo(&b)
@foo = b
self
end
def bar(&b)
#do stuff with @foo and b
end
T.
On 4/6/07, Joel VanderWerf [email protected] wrote:
More generally, though, the only way to pass more than one block to a
method is to turn all but one of the blocks into procs, like this:meth_with_two_blocks(proc {…}) { … }
I generally recommend using Kernel#lambda instead of Kernel#proc the
difference is subtle, but unless you want to allow non-local returns
from a block lamba is almost always the right choice.
–
Rick DeNatale
My blog on Ruby
http://talklikeaduck.denhaven2.com/
On Apr 6, 2007, at 1:15 AM, gaoxtwarrior wrote:
when it comes the method needs two block to accomplish a task,how
the ruby
do which? for example , the classical sum(filter,mapping,iterator)
(I have
forgotten the style, maybe,the one can search it in SICP)
Ruby’s block syntax is just a special (and very useful) case for a
single
block but you can construct proc objects and pass them directly if you
you have a need:
def merge(a,b,c)
[a.call, b.call, c.call].join(’/’)
end
result = merge( proc { “first block” }, proc { “second block”}, proc
{ “third block” } )
puts result # “first block/second block/third block”
Gary W.
On 4/7/07, Joel VanderWerf [email protected] wrote:
from a block lamba is almost always the right choice.
return
puts “didn’t get here”
foo_lambda
foo_proc_new
done–
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
Also, Proc.new (and proc in 1.9) do not check arguments strictly:
mylam = Proc.new {|x,y,z| p ‘hi’ }
=> #Proc:0x013fc75c@:3(irb)
mylam[1,2,3,4,5,6,7]
“hi”
=> nil
mylam[]
“hi”
=> nil
Rick DeNatale wrote:
Do you mean Proc.new? IIRC Kernel#proc and Kernel#lambda are aliases.
Proc.new is the one with non-local returns, at least as of 1.8.6.[1]
There is another reason to not use #proc, which I have yet to resign
myself to: it is going away in some future ruby, and we will have to
type two more characters each time we want to use it.
[1]
def m
foo_lambda = lambda do
puts “foo_lambda”
return
end
foo_proc = proc do
puts “foo_proc”
return
end
foo_proc_new = Proc.new do
puts “foo_proc_new”
return # non-local return
end
foo_proc.call
foo_lambda.call
foo_proc_new.call
puts “didn’t get here”
end
m
puts “done”
END
Output:
foo_proc
foo_lambda
foo_proc_new
done
On 4/7/07, Rick DeNatale [email protected] wrote:
Yep you’re right. I got the difference between a raw proc and a
lambda and the two methods.
“I got the difference between a raw proc and a lambda and the two
methods.”.sub(/lambda/,“lambda,”).sub(/methods/, “methods tied
together in my feeble mind”)
–
Rick DeNatale
My blog on Ruby
http://talklikeaduck.denhaven2.com/
On 4/7/07, Joel VanderWerf [email protected] wrote:
Do you mean Proc.new? IIRC Kernel#proc and Kernel#lambda are aliases.
Proc.new is the one with non-local returns, at least as of 1.8.6.[1]
Yep you’re right. I got the difference between a raw proc and a
lambda and the two methods.
There is another reason to not use #proc, which I have yet to resign
myself to: it is going away in some future ruby, and we will have to
type two more characters each time we want to use it.
Personally, I prefer lambda to proc, particularly since we are talking
about functional programming.
Makes me think of Alonzo Church every time I type it.
And Ruby saves me so many characters in so many other contexts
compared to most languages that it seems like a small thing anyway.
–
Rick DeNatale
My blog on Ruby
http://talklikeaduck.denhaven2.com/