0

I'm looking for something similar to #detect in enumerables, but not quite. This is what enumerable does:

[1, 2, 3].detect {|i| i > 1 } #=> 2

it returns the first instance of the array which matches the condition. Now, my purpose is to return the value of the block. Concern is not exactly the conditions, but for instance, the first which is not nil. Something like this:

[var1, var2, var3].wanted_detect {|var| another_function(var) } 

in which the function would return the first result of another_function call which isn't nil.

Mapping the values of applying the method on the variables and then using detect is not an option. This one would ideally have to work in lazy enumerators, for which the early mapping of all possible values is a no-go

ChuckE
  • 5,610
  • 4
  • 31
  • 59

1 Answers1

2
[var1, var2, var3].lazy.map { |var| another_function(var) }.reject(&:nil?).first

If you don't have access to Enumerable#lazy, it is easy enough to implement what you want:

module Enumerable
  def wanted_detect
    self.each do |obj|
      val = yield obj
      return val if val
    end
  end
end

Demo:

[1, 2, 3, 4].wanted_detect { |x| x*x if x > 2 }
# => 9

EDIT: Sorry, I missed the last paragraph till falsetru pointed it out.

Thanks for the comments, falsetru.

Amadan
  • 191,408
  • 23
  • 240
  • 301
  • 1
    OP said `Mapping the values of applying the method on the variables and then using detect is not an option.` – falsetru Jul 25 '13 at 09:30
  • In blocks, you are not calling `another_function`. It should be `another_function(var)`. – falsetru Jul 25 '13 at 09:34
  • no, I don't have access to lazy (1.9.3). correct me if i'm wrong, but doesn't compact return an array? that means that, by calling compact on the enumerable, i'll be transforming it in an array before calling first, thereby calling another_function unnecessarily on every element of my array? – ChuckE Jul 25 '13 at 13:21
  • i would like to use a combination on the existing API and not having to write my own enumerable implementation, i want to see if it's possible with the existing API. – ChuckE Jul 25 '13 at 13:22
  • I get the error `undefined method `compact' for #:map>` when trying to use `lazy` as described. – Rebecca Meritz Jul 20 '18 at 15:29
  • @RebeccaMeritz: You are absolutely correct, and I have no idea why no-one corrected me before. Edited. – Amadan Jul 22 '18 at 03:21