Code Examples for

Programming in Scala, Fifth Edition

Return to chapter index

8 Functions and Closures

Sample run of chapter's interpreter examples

8.1 Methods


// In file functions-and-closures/PadLines.scala object Padding: def padLines(text: String, minWidth: Int): String = val paddedLines = for line <- text.linesIterator yield padLine(line, minWidth) paddedLines.mkString("\n") private def padLine(line: String, minWidth: Int): String = if line.length >= minWidth then line else line + " " * (minWidth - line.length)

8.2 Local functions


// In file functions-and-closures/PadLines2.scala def padLines(text: String, minWidth: Int): String = def padLine(line: String, minWidth: Int): String = if line.length >= minWidth then line else line + " " * (minWidth - line.length) val paddedLines = for line <- text.linesIterator yield padLine(line, minWidth) paddedLines.mkString("\n")
// In file functions-and-closures/PadLines3.scala object Padding: def padLines(text: String, minWidth: Int): String = def padLine(line: String): String = if line.length >= minWidth then line else line + " " * (minWidth - line.length) val paddedLines = for line <- text.linesIterator yield padLine(line) paddedLines.mkString("\n")

8.3 First-class functions


(x: Int) => x + 1
val increase = (x: Int) => x + 1 increase(10) // 11
val addTwo = (x: Int) => val increment = 2 x + increment addTwo(10) // 12
scala> val someNumbers = List(-11, -10, -5, 0, 5, 10) val someNumbers: List[Int] = List(-11, -10, -5, 0, 5, 10) scala> someNumbers.foreach((x: Int) => println(x)) -11 -10 -5 0 5 10
scala> someNumbers.filter((x: Int) => x > 0) val res4: List[Int] = List(5, 10)

8.4 Short forms of function literals


scala> someNumbers.filter((x) => x > 0) val res5: List[Int] = List(5, 10)
scala> someNumbers.filter(x => x > 0) val res6: List[Int] = List(5, 10)

8.5 Placeholder syntax


scala> someNumbers.filter(_ > 0) val res7: List[Int] = List(5, 10)
scala> someNumbers.filter(x => x > 0) val res8: List[Int] = List(5, 10)
scala> val f = _ + _ ^ error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$plus(x$2))
scala> val f = (_: Int) + (_: Int) val f: (Int, Int) => Int = $$Lambda$1075/1481958694@289fff3c scala> f(5, 10) val res9: Int = 15

8.6 Partially applied functions


def sum(a: Int, b: Int, c: Int) = a + b + c
sum(1, 2, 3) // 6
val a = sum(_, _, _) // a has type (Int, Int, Int) => Int
a(1, 2, 3) // 6
a.apply(1, 2, 3) // 6
val b = sum(1, _, 3) // b has type Int => Int
b(2) // 6 b(5) // 9
val c = sum // c has type (Int, Int, Int) => Int
c(10, 20, 30) // 60

8.7 Closures


(x: Int) => x + more // how much more?
scala> (x: Int) => x + more 1 |(x: Int) => x + more | ^^^^ | Not found: more
var more = 1 val addMore = (x: Int) => x + more addMore(10) // 11
more = 9999 addMore(10) // 10009
val someNumbers = List(-11, -10, -5, 0, 5, 10) var sum = 0 someNumbers.foreach(sum += _) sum // -11
def makeIncreaser(more: Int) = (x: Int) => x + more
val inc1 = makeIncreaser(1) val inc9999 = makeIncreaser(9999)
inc1(10) // 11 inc9999(10) // 10009

8.8 Special function call forms


scala> def echo(args: String*) = | for arg <- args do println(arg) def echo(args: String*): Unit
scala> echo() scala> echo("one") one scala> echo("hello", "world!") hello world!
scala> val seq = Seq("What's", "up", "doc?") val seq: Seq[String] = List(What's, up, doc?) scala> echo(seq) 1 |echo(seq) | ^^^ | Found: (seq : Seq[String]) | Required: String
scala> echo(seq*) What's up doc?
def speed(distance: Float, time: Float) = distance / time speed(100, 10) // 10.0
speed(distance = 100, time = 10) // 10.0
speed(time = 10, distance = 100) // 10.0
// In file functions-and-closures/NamedDefault.scala // In same source file as class Rational object Rational: def apply(numer: Int, denom: Int = 1) = new Rational(numer, denom)
// In file functions-and-closures/NamedDefault.scala def point(x: Int = 0, y: Int = 0) = (x, y)
point(x = 42)
point(y = 1000)

8.9 ``SAM'' types


JButton button = new JButton(); // This is Java button.addActionListener( event -> System.out.println("pressed!") );
val button = new JButton button.addActionListener( _ => println("pressed!") )
trait Increaser: def increase(i: Int): Int
def increaseOne(increaser: Increaser): Int = increaser.increase(1)
increaseOne( new Increaser: def increase(i: Int): Int = i + 7 )
increaseOne(i => i + 7) // Scala

8.10 Tail recursion


// In file functions-and-closures/Approximate.scala def approximate(guess: Double): Double = if isGoodEnough(guess) then guess else approximate(improve(guess))
// In file functions-and-closures/Approximate.scala def approximateLoop(initialGuess: Double): Double = var guess = initialGuess while !isGoodEnough(guess) do guess = improve(guess) guess
// In file functions-and-closures/TailRecursion.scala def boom(x: Int): Int = if x == 0 then throw new Exception("boom!") else boom(x - 1) + 1
scala> boom(3) java.lang.Exception: boom! at .boom(<console>:5) at .boom(<console>:6) at .boom(<console>:6) at .boom(<console>:6) at .<init>(<console>:6) ...
public double approximate(double); Code: 0: aload_0 1: astore_3 2: aload_0 3: dload_1 4: invokevirtual #24; //Method isGoodEnough:(D)Z 7: ifeq 12 10: dload_1 11: dreturn 12: aload_0 13: dload_1 14: invokevirtual #27; //Method improve:(D)D 17: dstore_1 18: goto 2
// In file functions-and-closures/TailRecursion.scala def bang(x: Int): Int = if x == 0 then throw new Exception("bang!") else bang(x - 1)
scala> bang(5) java.lang.Exception: bang! at .bang(<console>:5) at .<init>(<console>:6) ...
// In file functions-and-closures/Misc.scala def isEven(x: Int): Boolean = if x == 0 then true else isOdd(x - 1) def isOdd(x: Int): Boolean = if x == 0 then false else isEven(x - 1)
// In file functions-and-closures/Misc.scala val funValue = nestedFun def nestedFun(x: Int): Unit = if x != 0 then println(x) funValue(x - 1)

8.11 Conclusion

For more information about Programming in Scala, Fifth Edition (the "Stairway Book"), please visit:

http://www.artima.com/shop/programming_in_scala_5ed

and:

http://booksites.artima.com/programming_in_scala_5ed

Copyright © 2007-2020 Artima, Inc. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.