Streams work nicely with infinite sequences. However, here you know your bounds; you just want to avoid all the intermediate collections that can come about as a by-product of functional programming. (Side Note: Euler 23 should be doable in profligate brute-force even on modest hardware; is it just that your heap is perhaps too small?)
If your main concern is memory, do consider using views. Like Streams, Views in Scala are lazy. But the semantics are different. Consider this:
(1 to 100000) map (_+1) filter (x => x % 2 == 0) map (x => x*x)
The intention here is function composition, but this will create several intermediate collections on the way: Each map
and filter
will return a new, potentially comparably sized collection. Views are one solution to obtain both performance (via memory efficiency) and compositionality: You just create your 'starting' collection as a view:
(1 to 100000 view) map (_+1) filter (x => x % 2 == 0) map (x => x*x)
Which would quickly return a SeqView
and not the usual Seq
- when the view is actually forced, your transformations (in map
and filter
) are effectively done as one as opposed to on different intermediate collections. Think of them as analogous to views on tables in SQL. Depending on how you plan on solving Euler Problem 23, views may be helpful. They are just one of the ways of leveraging laziness in Scala - See this post for the differences between views, streams and iterators: Stream vs Views vs Iterators