I'm working through the exercises and concepts of the book: Functional Programming in Scala. Say I need to define a constant
function, which returns an infinite stream by the given value.
Here is my version:
def constant[A](a: A): Stream[A] = Stream.cons(a, constant(a))
and the answer in GitHub:
def constant[A](a: A): Stream[A] = {
lazy val tail: Stream[A] = Cons(() => a, () => tail)
tail
}
The comment says the latter is more efficient than the former since it's just one object referencing itself. I can't understand this, any help would be greatly appreciated. (and sorry for my broken English :)
Streams will use the same functional programming concepts to iterate over collections of data in the functional style.
Scala is a language that features full support of Functional Programming as well as the Object-Oriented Paradigm. It is one of the most widely utilized languages by the Functional community, up to par with F#, and Haskell, Clojure, among others.
Streams in Java provide a functional approach to process a collection of objects. Stream. java provides different methods to process list elements, map(), flatMap(), filter(), sorted() etc, each of which takes a functional interface type as an argument.
Functional programming (FP) is a style of software development emphasizing functions that don't depend on program state. Functional code is easier to test and reuse, simpler to parallelize, and less prone to bugs than other code. Scala is an emerging JVM language that offers strong support for FP.
Say you define constant
the first way. Now,
constant(something)
This is one Cons
cell, and it has a reference to the lazy values something
and constant(something)
Cons(() => something, () => constant(something))
Now, let's try to get the 1000th element. We need to evaluate the tail, because we need to go deeper than just the first element. So, we execute constant(something)
, and we get a new Cons
cell that looks just like the original:
Cons(() => something, () => constant(something))
And we try to get 999th element of this Stream
. This is inefficient, because this object is the same as the one from before, so we just wasted our time making it. We will continue to waste time and memory making 1000 identical Cons
cells. (Excuse the terrible drawing.)
Now, define constant
the second way.
constant(something)
{ lazy val self = Cons(something, self); self }
Now, your Stream
simply has a reference to itself. Getting the tail of this Stream
does not create a new Cons
cell; it simply returns the original stream (self.tail eq self
), which means you waste no memory, and the time cost goes down because you also don't waste time allocating and filling that memory.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With