[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Enumerable#detect_result ?

Yossef Mendelssohn

11/24/2007 10:13:00 PM

Actual code from a recent project:

# This is bunk, but I'm tired and can't think of the right way to
do this
# I was trying formats.detect, but that just returns the format,
not the result
result = nil
formats.each do |f|
result = f.process(mesg)
break if result
end

In this context, 'formats' is an array of format objects, each of
which represents a format a message can take. The process method takes
in a message, checks it against the format object's configuration, and
returns either nil (if there was no match) or some useful value.

Thanks to testing, my original concept of

formats.detect { |f| f.process(mesg) }

was rejected as being wrong. After all, I want the result of the
process call, not the format object. I could go with collect/detect,
but knowing I want the first makes that rather pointless, especially
if processing could be expensive and the array could be long.

Is there anything like Enumerable#detect_result? Is there any desire
for it? Is there any better name?

--
-yossef

7 Answers

Robert Dober

11/24/2007 11:57:00 PM

0

On Nov 24, 2007 11:12 PM, Yossef Mendelssohn <ymendel@pobox.com> wrote:
> Actual code from a recent project:
>
> # This is bunk, but I'm tired and can't think of the right way to
> do this
> # I was trying formats.detect, but that just returns the format,
> not the result
> result = nil
> formats.each do |f|
> result = f.process(mesg)
> break if result
> end
hmm yeah I also feel the need for something like map_first sometimes,
but there is no such beast.

you can simplify the code above a little bit

formats.each do | f |
result = ...
break result if result
end

and if performance is not a problem the following is an alternative

formats.map{ |f| f.process( mesg )}.detect{|x| x}
if x can never be false that can be written as
formats.map{ ... }.compact.first or use facets
formats.map_if{ ... }.first if there are possible false values.

I do not know a standard or facets built in method that will stop
iterating and return the block's value, hopefully I am wrong ;)

HTH
Robert




>
> In this context, 'formats' is an array of format objects, each of
> which represents a format a message can take. The process method takes
> in a message, checks it against the format object's configuration, and
> returns either nil (if there was no match) or some useful value.
>
> Thanks to testing, my original concept of
>
> formats.detect { |f| f.process(mesg) }
>
> was rejected as being wrong. After all, I want the result of the
> process call, not the format object. I could go with collect/detect,
> but knowing I want the first makes that rather pointless, especially
> if processing could be expensive and the array could be long.
>
> Is there anything like Enumerable#detect_result? Is there any desire
> for it? Is there any better name?
>
> --
> -yossef
>
>



--
what do I think about Ruby?
http://ruby-smalltalk.blo...

MonkeeSage

11/25/2007 3:18:00 AM

0

On Nov 24, 4:12 pm, Yossef Mendelssohn <ymen...@pobox.com> wrote:

> Is there anything like Enumerable#detect_result? Is there any desire
> for it? Is there any better name?

Would this work?

module Enumerable
def detect_result(ifnone=nil, &block)
self.each { |x|
result = block.call(x)
return result if result
}
if ifnone
then ifnone.call
else nil
end
end
end

Regards,
Jordan

Trans

11/25/2007 6:00:00 AM

0



On Nov 24, 5:12 pm, Yossef Mendelssohn <ymen...@pobox.com> wrote:
> Actual code from a recent project:
>
> # This is bunk, but I'm tired and can't think of the right way to
> do this
> # I was trying formats.detect, but that just returns the format,
> not the result
> result = nil
> formats.each do |f|
> result = f.process(mesg)
> break if result
> end

A little better.

result = nil
formats.find do |f|
result = f.process(mesg)
end

T.

Yossef Mendelssohn

11/25/2007 6:28:00 AM

0

On Nov 25, 12:00 am, Trans <transf...@gmail.com> wrote:
> On Nov 24, 5:12 pm, Yossef Mendelssohn <ymen...@pobox.com> wrote:
>
> > Actual code from a recent project:
>
> > # This is bunk, but I'm tired and can't think of the right way to
> > do this
> > # I was trying formats.detect, but that just returns the format,
> > not the result
> > result = nil
> > formats.each do |f|
> > result = f.process(mesg)
> > break if result
> > end
>
> A little better.
>
> result = nil
> formats.find do |f|
> result = f.process(mesg)
> end
>
> T.

Well, dang. I would say that's obvious, but if that were actually the
case I would've thought of it. Nice one.

--
-yossef

MonkeeSage

11/25/2007 8:59:00 AM

0

Yossef,

Just curious, but does the detect_results method for the Enumerable
module that I listed above, work for your example:

results = formats.detect_results { |f| f.process(mesg) }

?

Regards,
Jordan

Yossef Mendelssohn

11/25/2007 2:53:00 PM

0


On Nov 25, 3:00 am, MonkeeSage <MonkeeS...@gmail.com> wrote:
> Yossef,
>
> Just curious, but does the detect_results method for the Enumerable
> module that I listed above, work for your example:
>
> results = formats.detect_results { |f| f.process(mesg) }
>
> ?
>
> Regards,
> Jordan

I didn't bother to try. It looks like it'll work just fine. I like the
idea of specifying an alternate value if nothing matches, but it's
always odd to pass two blocks to a method.

--
-yossef

MonkeeSage

11/25/2007 3:12:00 PM

0

On Nov 25, 8:52 am, Yossef Mendelssohn <ymen...@pobox.com> wrote:

> I didn't bother to try. It looks like it'll work just fine. I like the
> idea of specifying an alternate value if nothing matches, but it's
> always odd to pass two blocks to a method.

It's actually the same thing that detect() does, I just made it return
the value of the first True instance, rather than the object. If you
look at the docs for Enumerable#detect, it's the same semantics for
ifnone.

Regards,
Jordan