[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Question on Procs

bparanj@gmail.com

4/30/2008 4:26:00 AM

What is the difference between this:

list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

def make_filter(predicate, list)
result = []
list.each do |element|
result << element if predicate.call(element)
end
result
end

require 'rubygems'
require 'facets/integer/ordinal'

filter_ths = make_filter( lambda { |x| x.ordinal =~ /th$/ ? true :
false }, list)

p filter_ths

and this:

list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

def make_filter(predicate)
lambda do |list|
result = []
list.each do |element|
result << element if predicate.call(element)
end
result
end
end

require 'rubygems'
require 'facets/integer/ordinal'

filter_ths = make_filter( lambda { |x| x.ordinal =~ /th$/ ? true :
false })

p filter_ths.call(list)

I am not clear on the advantage of returning proc object vs just the
result as an array. TIA.
2 Answers

benjohn

4/30/2008 10:20:00 AM

0

> What is the difference between this:

*snip*

> filter_ths = make_filter( lambda { |x| x.ordinal =~ /th$/ ? true :
> false }, list)
>
> p filter_ths
>
> and this:

*snip*

> filter_ths = make_filter( lambda { |x| x.ordinal =~ /th$/ ? true :
> false })
>
> p filter_ths.call(list)
>
> I am not clear on the advantage of returning proc object vs just the
> result as an array. TIA.

The difference is abstraction, if I understand your question.

In the first case, you've filtered something (an enumerable type) and
built a result array.

In the second case, you have built a little machine (the proc) that will
take an enumerable type and filter it to give an array. This machine is
probably a more reusable thing.

As a motivating example, lets say you have an object called Trawler (or a
group of objects working together) that find interesting web pages to
store. In the former case, Trawler will have to tell you about some web
pages it's found that might be interesting. You can filter them, and then
tell it the ones you want it to store. In the latter case, you can give
Trawler a filter, and it can then be autonimous - it can filter pages to
see if they're interesting.

:-) Or have I totally missed the right end of your question?

You can write these more concisely like this (I've not tested this)...

cool_pages = web_pages.find_all {|x| is_this_a_cool_page(x)}

verses...

page_filter = proc {|array| array.find_all {|x| is_this_a_cool_page?(x)}}
cool_pages = page_filter.call(web_pages)

Cheers,
Benjohn



Eric I.

4/30/2008 10:03:00 PM

0

On Apr 30, 12:26 am, "bpar...@gmail.com" <bpar...@gmail.com> wrote:
> I am not clear on the advantage of returning proc object vs just the
> result as an array. TIA.

Hi Bala,

From the short example you provide, there really is no advantage to
returning a Proc. However, if you needed to perform the same
filtering operation in more than one place in your code, there might
be an advantage to re-using the same filter, so that code does not
have to be repeated.

Or alternatively, say you had an application that offered its users
the ability to apply many commonly used filters (perhaps via a drop-
down menu). Each of these filters might have an associated name, use
example, and the Proc used to implement it. Well, name, example, and
Proc could be members of a hash or alternatively instance variables in
an instance of some Filter class.

As Benjohn pointed out, it's a matter of abstraction. That Ruby
allows one to store Procs in variables, have methods take Procs as
parameters or return a Proc means Ruby has "first class functions".
You can read more about the concept here:

http://en.wikipedia.org/wiki/First-clas...

I suspect the code you showed us is someone's attempt to demonstrate
the power of Procs and first class functions. That kind of filtering
would more commonly be done with Enumerable#select or
Enumerable#reject. Since Arrays are Enumerable, the code would
become:

list_2 = list_1.select { |item| item.ordinal =~ /th$/ }

(Also note that because the result of the =~ operator can be evaluated
as true or false, the trinary conditional operator ?: is unnecessary.)

Eric
----
Are you looking for on-site Ruby or Ruby on Rails training
that's been highly reviewed by former students?
http://Lea...