Skip to content

Instantly share code, notes, and snippets.

@MarounMaroun
Created November 22, 2017 11:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MarounMaroun/a0f6d7b972cbf73059115fd35776aaea to your computer and use it in GitHub Desktop.
Save MarounMaroun/a0f6d7b972cbf73059115fd35776aaea to your computer and use it in GitHub Desktop.
Strict VS Lazy evaluation in Scala
/**
* Assume we are interested in finding the first two even numbers in a very big file.
* Since we love functional programming, we don't want to use the traditional for loops.
* Instead, we want to apply a series of function to get the desired output.
*/
// for the sake of the example, I assume the input is found in a list, not a file
var l = List(1, 47, 38, 53, 51, 67, 39, 46, 93, 54, 45, 33, 87, 96, 100, 4, 84, 17, 31, 81, 88, 35, 36)
// we don't really need toList here, but since we're assuming the data is coming from a file, I'll use it anyway
var strict_result = l.toList.filter(_ % 2 == 0).take(2)
// great! The result printed is 38 and 46
strict_result foreach println
// but did you notice how the list was created?
// OK, that's what really happened:
// 1. we opened the file (not really)
// 2. got ALL the lines (by using toList)
// 3. we filtered ALL the lines to get even numbers
// 4. finally we took the first two numbers
// that's because the List is a strict data structure. So when we call toList, it evaluates *immediately*,
// and only when we have the whole list (file lines in our original assumption), it does the filtering
// so what we should do? You guessed it right! We should be using a data structure that is *lazy* evaluated.
// Stream for the rescure!
var lazy_result = l.toStream.filter(_ % 2 == 0).take(2)
// in order to better understand what happened here, let's try the following
l.toStream
// prints "scala.collection.immutable.Stream[Int] = Stream(1, ?)"
// what is this? toStream evaluates to only one element - the first item in the list.
// the next element is "?", which indicates that the stream has not evaluated the next element,
// and that's because toStream is a lazy function, and the next line (list item in this case) is evaluated when we use it.
// now when we apply the "filter" function, it will start reading next line until we get the FIRST even number.
// when we apply "take(2)", no action is performed, but it knows that it should pick two numbers. It doesn't evaluate until
// we use both numbers:
strict_result foreach println
// now if we print laze_result, we should get the full result:
lazy_result
// prints "scala.collection.immutable.Stream[Int] = Stream(38, 46)"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment