[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

about functional programming

gaoxtwarrior

4/6/2007 5:11:00 AM

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)


9 Answers

Joel VanderWerf

4/6/2007 5:40:00 AM

0

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 {...}) { ... }

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Gary Wright

4/6/2007 5:48:00 AM

0


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 Wright




Robert Klemme

4/6/2007 10:04:00 AM

0

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+(x*3)}
=> 30
irb(main):012:0> num.select {|x| x<5}.map {|x| x*3}.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

Trans

4/7/2007 12:16:00 PM

0



On Apr 6, 1:15 am, "gaoxtwarrior" <g...@cssweb.com.cn> 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.


Rick DeNatale

4/7/2007 6:02:00 PM

0

On 4/6/07, Joel VanderWerf <vjoel@path.berkeley.edu> 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.denh...

Joel VanderWerf

4/7/2007 6:24:00 PM

0

Rick DeNatale wrote:
> On 4/6/07, Joel VanderWerf <vjoel@path.berkeley.edu> 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.
>

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

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Chris Carter

4/7/2007 6:32:00 PM

0

On 4/7/07, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:
> Rick DeNatale wrote:
> > On 4/6/07, Joel VanderWerf <vjoel@path.berkeley.edu> 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.
> >
>
> 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
>
> --
> 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@(irb):3>
>> mylam[1,2,3,4,5,6,7]
"hi"
=> nil
>> mylam[]
"hi"
=> nil
--
Chris Carter
concentrationstudios.com
brynmawrcs.com

Rick DeNatale

4/7/2007 7:12:00 PM

0

On 4/7/07, Joel VanderWerf <vjoel@path.berkeley.edu> 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.
<G>


--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denh...

Rick DeNatale

4/7/2007 7:17:00 PM

0

On 4/7/07, Rick DeNatale <rick.denatale@gmail.com> 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.denh...