scalabeginner

Higher-Order Functions and Closures

Write and use higher-order functions: function literals, closures, currying, and partial application.

scala
// Function types
val double: Int => Int = _ * 2
val add: (Int, Int) => Int = _ + _
val isPositive: Int => Boolean = _ > 0

// Higher-order function
def applyTwice[A](f: A => A, x: A): A = f(f(x))

// Function composition
val addOne: Int => Int = _ + 1
val triple: Int => Int = _ * 3
val addOneThenTriple = triple compose addOne  // triple(addOne(x))
val tripleThenAddOne = triple andThen addOne  // addOne(triple(x))

// Currying
def multiply(a: Int)(b: Int): Int = a * b
val double2 = multiply(2)    // partially applied
val triple2 = multiply(3)

// Custom control structure
def withResource[A <: AutoCloseable, B](res: A)(f: A => B): B =
  try f(res) finally res.close()

def retry[T](n: Int)(block: => T): T =
  var lastError: Throwable = null
  for i <- 1 to n do
    try return block
    catch case e: Throwable =>
      lastError = e
      println(s"Attempt $i failed: ${e.getMessage}")
  throw lastError

def timed[T](label: String)(block: => T): T =
  val start = System.nanoTime()
  val result = block
  val elapsed = (System.nanoTime() - start) / 1e6
  println(f"$label: $elapsed%.2f ms")
  result

// Closures
def makeCounter(): () => Int =
  var count = 0
  () => { count += 1; count }

// Partial functions
val safeDivide: PartialFunction[(Int, Int), Double] =
  case (a, b) if b != 0 => a.toDouble / b

@main def run(): Unit =
  println(applyTwice(double, 3))        // 12
  println(applyTwice[String](_ + "!", "Hi"))  // Hi!!

  println(addOneThenTriple(5))  // 18
  println(tripleThenAddOne(5))  // 16

  println(double2(21))   // 42
  println(triple2(14))   // 42

  // Custom control structures
  val result = timed("computation") {
    (1 to 1_000_000).sum
  }
  println(s"Result: $result")

  // Closure
  val counter = makeCounter()
  println(counter())  // 1
  println(counter())  // 2
  println(counter())  // 3

  // Partial function
  println(safeDivide.isDefinedAt((10, 0)))  // false
  println(safeDivide(10, 3))  // 3.333...

  // List of functions
  val transforms: List[Int => Int] = List(_ + 1, _ * 2, _ - 3)
  val pipeline = transforms.reduce(_ andThen _)
  println(pipeline(10))  // (10+1)*2-3 = 19

Use Cases

  • Building custom control structures
  • Function composition pipelines
  • Reusable behavior with closures

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.