Functional Programming in Scala
Paul Chiusano, Runar Bjarnason
Format: PDF / Kindle (mobi) / ePub
Functional programming (FP) is a programming style emphasizing functions that return consistent and predictable results regardless of a program's state. As a result, functional code is easier to test and reuse, simpler to parallelize, and less prone to bugs. Scala is an emerging JVM language that offers strong support for FP. Its familiar syntax and transparent interoperability with existing Java libraries make Scala a great place to start learning FP.
Functional Programming in Scala is a serious tutorial for programmers looking to learn FP and apply it to the everyday business of coding. The book guides readers from basic techniques to advanced topics in a logical, concise, and clear progression. In it, they'll find concrete examples and exercises that open up the world of functional programming.
Purchase of the print book comes with an offer of a free PDF, ePub, and Kindle eBook from Manning. Also available is all code from the book.
Function2[Int,Int,Boolean], which is usually written (Int,Int) => Boolean. Note that the Function2 interface (known in Scala as a "trait") has a single method called apply . And when we call the lessThan function with lessThan(10, 20), it is really syntax sugar for calling its apply method: scala> val b = lessThan.apply(10, 20) b: Boolean = true Function2 is just an ordinary trait (i.e. an interface) provided by the standard Scala library (API docs link) to represent function objects that take
by need, or it's said to be lazy. We'll often refer to unevaluated parameters in Scala as by-name parameters. Note also that the terms laziness or lazy evaluation are sometimes used informally to refer to any sort of non-strict evaluation, not necessarily evaluation by need. When you encounter the word "lazy" in this book, you can assume that we are using an informal definition. 5.2 An extended example: lazy lists Let's now return to the problem posed at the beginning of this chapter. We are
functional library, you usually have some ideas about what you generally want to be able to do, and the difficulty in the design process is in refining these ideas and finding a data type that enables the functionality you want. In our case, we'd like to be able to "create parallel computations", but what does that mean exactly? Let's ©Manning Publications Co. We welcome reader comments about anything in the manuscript — other than typos and other simple mistakes. These will be cleaned up during
sortPar(l: Par[List[Int]]): Par[List[Int]] = map2(l, unit(()))((a, _) => a.sorted) Nice. We can now tell a Par[List[Int]] that we would like that list sorted. But we can easily generalize this further. We can "lift" any function of type A => B to become a function that takes Par[A] and returns Par[B]. That is, we can map any function over a Par: def map[A,B](fa: Par[A])(f: A => B): Par[B] = map2(fa, unit(()))((a,_) => f(a)) For instance, sortPar is now simply this: def sortPar(l:
exhaustively enumerate a sequence of values, and be notified somehow that all possible values have been generated. If we can get through all possible values without finding a failing case, this is an actual proof that our property holds over its domain. Clearly exhaustive generation won't always be feasible, but in some cases it might be. As a simple example, a Gen[Boolean] could first generate true, then false, then report it was done generating values. Likewise for the expression