Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Idiomatic Ruby - Execute a function until it returns a nil, collecting its values into a list

I stole my title from this post: Executes a function until it returns a nil, collecting its values into a list

That question refers to Lisp and is, frankly, over my head. However, I think that his question--translated into Ruby--is exactly my own:

What's the best way to create a conditional loop in [Ruby] that executes a function until it returns NIL at which time it collects the returned values into a list?

My current, clunky approach is this:

def foo
   ret = Array.new
   x = func() # parenthesis for clarity (I'm not a native Ruby coder...)
   until x.nil?
     ret << x
     x = func() 
   end
   ret
end

This code snippet will do what I want...but I know there is a cleaner, more idiomatically Ruby approach...right?

like image 461
Xuor Avatar asked Jul 31 '11 00:07

Xuor


2 Answers

Funny how nobody suggested Enumerator and its take_while method, to me it seems just fit:

# example function that sometimes returns nil
def func
  r = rand(5)
  r == 0 ? nil : r
end

# wrap function call into lazy enumerator
enum = Enumerator.new{|y|
  loop {
    y << func()
  }
}

# take from it until we bump into a nil
arr = enum.take_while{|elem|
  !elem.nil?
}

p arr
#=>[3, 3, 2, 4, 1, 1]
like image 165
Mladen Jablanović Avatar answered Oct 07 '22 01:10

Mladen Jablanović


I guess this looks more like Ruby:

def foo
  r = nil; [].tap { |a| a << r until (r = yield).nil? }
end
like image 30
Mario Uher Avatar answered Oct 07 '22 00:10

Mario Uher