Forum: Ruby about functional programming

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
gaoxtwarrior (Guest)
on 2007-04-06 09:16
(Received via mailing list)
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)
Joel VanderWerf (Guest)
on 2007-04-06 09:40
(Received via mailing list)
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 {...}) { ... }
Gary W. (Guest)
on 2007-04-06 09:48
(Received via mailing list)
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.
Robert K. (Guest)
on 2007-04-06 14:06
(Received via mailing list)
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 (Guest)
on 2007-04-07 16:16
(Received via mailing list)
On Apr 6, 1:15 am, "gaoxtwarrior" <removed_email_address@domain.invalid> 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 D. (Guest)
on 2007-04-07 22:03
(Received via mailing list)
On 4/6/07, Joel VanderWerf <removed_email_address@domain.invalid> 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/
Joel VanderWerf (Guest)
on 2007-04-07 22:25
(Received via mailing list)
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
Chris C. (Guest)
on 2007-04-07 22:33
(Received via mailing list)
On 4/7/07, Joel VanderWerf <removed_email_address@domain.invalid> 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@(irb):3>
>> mylam[1,2,3,4,5,6,7]
"hi"
=> nil
>> mylam[]
"hi"
=> nil
Rick D. (Guest)
on 2007-04-07 23:12
(Received via mailing list)
On 4/7/07, Joel VanderWerf <removed_email_address@domain.invalid> 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.denhaven2.com/
Rick D. (Guest)
on 2007-04-07 23:17
(Received via mailing list)
On 4/7/07, Rick DeNatale <removed_email_address@domain.invalid> 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/
This topic is locked and can not be replied to.