Getting FunctionalWhat is Functional Programming (FP)?Creating ListsNil and ::head, tail, and isEmptytake, drop, and splitAttoString and mkStringzip and unzipHigher-order functionsAbbreviationssortWithforall and existsforeachLeast upper boundClosuresmapflatMapfilterSome Map methodsAnother Map method“Houston, we have a problem.”The EndGetting Functional2What is Functional Programming (FP)?In FP,Functions are first-class objects. That is, they are value s, just like other objects are values, and can be treated as suchFunctions can be assigned to variables, passed as parameters to higher-order functions, returned as results of functionsThere is some way to write function literalsFunctions should only transform their inputs into their outputsA function should have no side effectsIt should not do any input/outputIt should not change any state (any external data)Given the same inputs, a function should produce the same outputs, every timeBut we need random numbers, date and time, etc.Functions have referential transparency—any given function call could safely be replaced by the function’s result23Creating Listsscala> List('a', 'b', 'c')res0: List[Char] = List(a, b, c)scala> "abc" toListres1: List[Char] = List(a, b, c)scala> "Welcome to Scala" split(" ")res2: Array[java.lang.String] = Array(Welcome, to, Scala)scala> val scala = "Scala" toListscala: List[Char] = List(S, c, a, l, a)scala> "Hello" :: scalares3: List[Any] = List(Hello, S, c, a, l, a)34Nil and ::scala> List()res4: List[Nothing] = List()scala> Nilres5: scala.collection.immutable.Nil.type = List()scala> List() == Nilres6: Boolean = truescala> List[String]()res7: List[String] = List()scala> "xyz" :: Nilres8: List[java.lang.String] = List(xyz)scala> "abc" :: "xyz" :: Nilres9: List[java.lang.String] = List(abc, xyz)45head, tail, and isEmptyscala> val penn = "Pennsylvania" toListpenn: List[Char] = List(P, e, n, n, s, y, l, v, a, n, i, a)scala> penn headres10: Char = Pscala> penn tailres11: List[Char] = List(e, n, n, s, y, l, v, a, n, i, a)scala> penn isEmptyres12: Boolean = falsescala> Nil isEmptyres13: Boolean = truescala> Nil headjava.util.NoSuchElementException: head of empty list (plus many more lines!)56take, drop, and splitAtscala> pennres16: List[Char] = List(P, e, n, n, s, y, l, v, a, n, i, a)scala> penn take 4res17: List[Char] = List(P, e, n, n)scala> penn drop 4res18: List[Char] = List(s, y, l, v, a, n, i, a)scala> penn splitAt 4res19: (List[Char], List[Char]) = (List(P, e, n, n),List(s, y, l, v, a, n, i, a))scala> penn.splitAt(4)res20: (List[Char], List[Char]) = (List(P, e, n, n),List(s, y, l, v, a, n, i, a))67toString and mkStringscala> List(1, 2, 3).toStringres25: String = List(1, 2, 3)scala> List(1, 2, 3).toString == "List(1, 2, 3)"res26: Boolean = truescala> List(1, 2, 3) mkString(" is less than ")res27: String = 1 is less than 2 is less than 3scala> List(1, 2, 3) mkString("*")res28: String = 1*2*3scala> List(1, 2, 3) mkString("<: ", "--", " :>")res29: String = <: 1--2--3 :>scala> List(1, 2, 3) mkString("(", ", ", ")")res30: String = (1, 2, 3)78zip and unzipscala> val words = "one two three" split " "words: Array[java.lang.String] = Array(one, two, three)scala> val numbers = List(1, 2, 3, 4, 5)numbers: List[Int] = List(1, 2, 3, 4, 5)scala> val z = words zip numbersz: Array[(java.lang.String, Int)] = Array((one,1), (two,2), (three,3))scala> val zz = numbers zip wordszz: List[(Int, java.lang.String)] = List((1,one), (2,two), (3,three))scala> z toMapres31: scala.collection.immutable.Map[java.lang.String,Int] = Map((one,1), (two,2), (three,3))scala> zz unzipres32: (List[Int], List[java.lang.String]) = (List(1, 2, 3),List(one, two, three))89Higher-order functionsThe basic syntax of a function literal is parameter_list => function_bodyA higher-order function is one that takes a function as a parameter, or returns a function as a resultscala> val brag = "Scala is great!" toListbrag: List[Char] = List(S, c, a, l, a, , i, s, , g, r, e, a, t, !)scala> brag count((ch: Char) => ch == 'a')res34: Int = 3scala> brag count((ch: Char) => !(ch isLetter))res35: Int = 3scala> "Scala is great!".toList.count((ch: Char) => ch < 'f')res36: Int = 9scala> "aeiou" contains 'e'res37: Boolean = truescala> "Scala is great!".toList.count((ch: Char) => "aeiou" contains ch)res38: Int = 5910AbbreviationsIn a literal function, you can usually omit the type (and, if there’s only one parameter, the parentheses)scala> bragres40: List[Char] = List(S, c, a, l, a, , i, s, , g, r, e, a, t, !)scala> brag count((ch: Char) => ch == 'a')res41: Int = 3scala> brag count (ch => ch == 'a')res42: Int = 3In fact, if there is only one parameter, used once, you can omit the parameter and the => and just use _ to stand in for the parameterscala> brag count (_ == 'a')res44: Int = 3Let me repeat that: Used oncescala> brag count (_ == 'a' || _ == 'e')<console>:7: error: wrong number of parameters; expected = 1 brag count (_ == 'a' || _ == 'e')1011sortWithscala> brag sortWith((x, y) => x < y)res49: List[Char] = List( , , !, S, a, a, a, c, e, g, i, l, r, s, t)Since there are two parameters, we can use two underscoresscala> brag sortWith (_ < _)res50: List[Char] = List( , , !, S, a, a, a, c, e, g, i, l, r, s, t)Order matters!scala> brag sortWith (_ > _)res52: List[Char] = List(t, s, r, l, i, g, e, c, a, a, a, S, !, , )1112forall and existsWhereas count returns an Int, forall and exists return a Booleanscala> val n = List(3, 1, 4, 1, 6)n: List[Int] = List(3, 1, 4, 1, 6)scala> n forall(x => x < 8)res53: Boolean = truescala> n forall(x => x < 5)res54: Boolean = falsescala> n exists(_ < 5)res55: Boolean = truescala> n exists(_ > 8)res56: Boolean = false1213foreachforeach returns the (uninteresting) Unit valuescala> val brag = List("Scala", "is", "great!")brag: List[java.lang.String] = List(Scala, is, great!)scala> brag foreach (println(_))Scalaisgreat!scala> brag foreach(println)Scalaisgreat!scala> List(3, 1, 4, 1, 6) foreach (x => if (x > 1) println(x))3461314Least upper boundThe following list contains only integers:scala> val list = List(1, 2, 3)list:
View Full Document