On Aug 6, 2008, at 08:40 , tphyahoo wrote:

> t = ( putStrLn . show . sum . takeWhile (<=4000000) . filter even )
> fibs2
> fibs2 = 1 : 2 : zipWith (+) fibs2 (tail fibs2)

Gives me hives personally... I've never been able to handle the syntax  
of haskell.

> but it relies on laziness and who knows what other magic.

The laziness I'm fine with... the other magic? not so much.

> I decided to see if I could find a ruby solution that was more
> haskellish. It turns I can... almost.

Ignoring my haskell bias for a bit... I'd recommend doing this, with  
any pairing of languages. Find the idiomatic response appropriate for  
the target language and you'll have a better time.

> There is a ruby library for laziness
>
> # http://lazylist.rubyforge.org/

I've not used this personally, I suspect using it is the problem.

> and it would seem to do what I want. But it hangs for some reason.
>
> I have poor sense of ruby culture. Should I report this as a bug? Is
> it even a bug? Do people ever use laziness, or is this crazy
> experimentation?

Assuming it is a bug, yes, report it. Again, not having used the  
library, I can't really weigh in whether this behavior is a bug or not.

> require 'rubygems'
> require 'lazylist' # http://lazylist.rubyforge.org/
>
> # Solve Project Euler problem 2: sum fibonacci numbers <= 4_000_000,
> which are even.
> fibs = ( LazyList.tabulate(0) { |x| x < 2 ? 1 : fibs[x-2] +
> fibs[x-1] } )

so, according to the doco, tabulate is a generator function that  
starts at 0 and yields the block on each successive succ.

(stop with all the parens)

> fibsUnder4M = ( fibs.partition{ |x| x <= 4_000_000 })[0]

partition is customized to return two lazy lists, so this _should_ be  
fine.

> evenFibsUnder4M = fibsUnder4M.select{ |x| x %2 == 0}

likewise, select is customized to return a lazy list. again, fine.

> # hangs
> puts evenFibsUnder4M.take(10) # this is ok
> puts evenFibsUnder4M.take(11) # this hangs, laptop gets hot, fan turns
> on...

presumably the take actually executes and generates elements from the  
lazy list, unwinding back through the select, the partition, and  
finally the tabulate block. This all looks kosher to me on the surface  
(albeit a bit more complicated than necessary because you're trying to  
match haskell.

So, I would think that you've discovered a bug in the LazyList impl,  
as your logic seems sound.

Here is my ruby-idiomatic solution to the problem:

> # Solve Project Euler problem 2:
> #   sum fibonacci numbers <= 4_000_000, which are even.
>
> $fib = {} # simple memoization
> def fib x
>   $fib[x] ||= x < 2 ? 1 : fib(x-2) + fib(x-1)
> end
>
> # fib 33 > 4m
> fibs = (1..32).map { |n| fib n }.reject { |n| n % 2 == 1 }
>
> sum = 0
> fibs.each do |n|
>   sum += n
> end
>
> p sum
> # => 4613732

because of the memoization, it runs incredibly fast. If I wasn't  
allowed to predetermine the upper bound of the calculation, I'd wrap  
that up in a simple loop with a conditional... Nothing fancy.