views:

219

answers:

2

I am currently doing some Project Euler problems and the earlier ones often involve things like Fibonacci numbers or primes. Iterating over them seems to be a natural fit for LINQ, at least in readability and perceived "elegance" of the code (I'm trying to use language-specific features where possible and applicable to get a feel for the languages).

My problem is now, if I only need a set of numbers up to a certain limit, how should I best express this? Currently I have hard-coded the respective limit in the iterator but I'd really like the enumerator to return the list until something outside decides not to query it anymore, since it's over a certain limit. So basically that I have a potentially infinite iterator but I only take a finite set of numbers from it. I know such things are trivial in functional languages, but I wonder whether C# allows for that, too. The only other idea I had would be to have an iterator Primes(long) that returns primes up to a certain limit, likewise for other sequences.

Any ideas?

+7  A: 

Most of the LINQ methods (Enumerable class) are lazy. So for instance, there's nothing wrong with:

var squares = Enumerable.Range(0, Int32.MaxValue).Select(x=>x*x);

You can use the Take method to limit the results:

var 10squares = squares.Take(10);

var smallSquares = squares.TakeWhile(x => x < 10000);

Edit: The things you need to avoid are functions that return "lazily" but have to consume the entire enumerable to produce a result. For example, grouping or sorting:

var oddsAndEvens = Enumerable.Range(0, Int32.MaxValue)
                             .GroupBy(x => x % 2 == 0);
foreach (var item in oddsAndEvens) {
  Console.WriteLine(item.Key);
}

(That'll probably give you an OutOfMemoryExeption on 32-bit.)

MichaelGG
Ah, ok, didn't know TakeWhile so far. I just thought that using Where to select the numbers I want wouldn't work as LINQ has no idea that the numbers are increasing, for example. That sounds nice, indeed :)
Joey
+1, nice summary. I also tried to elaborate a little on this topic: http://blog.casualdev.net/2009/10/linq-and-infinite-enumerations.html
Alexander Abramov