Enumerable#detect_result ?

Y

Yossef Mendelssohn

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?
 
R

Robert Dober

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
 
M

MonkeeSage

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
 
T

Trans

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.
 
Y

Yossef Mendelssohn

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.
 
M

MonkeeSage

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
 
Y

Yossef Mendelssohn

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.
 
M

MonkeeSage

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,968
Messages
2,570,152
Members
46,697
Latest member
AugustNabo

Latest Threads

Top