Function Currying and Object-Oriented Programming in Scala

Function Currying

Currying transforms a function with multiple arguments into a series of functions each taking a single argument. This technique essentially creates closures.

package com.example.functions

object CurryingExample {
  def main(args: Array[String]): Unit = {
    // Basic function to find the larger of two integers
    def largerValue(x: Int, y: Int): Int = if (x > y) x else y
    println(largerValue(3, 5))

    // Higher-order function using currying
    def largerCurried(first: Int) = {
      def inner(second: Int): Int = if (first > second) first else second
      inner _
    }

    val partial = largerCurried(4)
    println(partial(2))
    println(partial(1))
    println(largerCurried(5)(7))

    // Simplified curried function definition
    def curriedLarger(first: Int)(second: Int) = if (first > second) first else second
    println(curriedLarger(4)(3))
    
    val result = curriedLarger(3)(5)
    println(result)
  }
}

Call-by-Name Parameters

Call-by-name parameters evaluate the argument expression each time it is referenced within the function.

package com.example.functions

object CallByNameDemo {
  def main(args: Array[String]): Unit = {
    // Accepts any block yielding an Int
    def doubleEval(expr: => Int): Unit = println(expr)

    doubleEval(3)
    doubleEval(if (3 > 5) 3 else 5)

    def sum(a: Int, b: Int): Int = a + b
    doubleEval(sum(3, 5))

    // Requires a function of type (Int, Int) => Int
    def compute(func: (Int, Int) => Int): Unit = println(func)
    compute(sum)
  }
}

Implementing a custom while loop using call-by-name parameters:

package com.example.functions

object CustomLoop {
  def main(args: Array[String]): Unit = {
    def customWhile(predicate: => Boolean)(action: => Unit): Unit = {
      if (predicate) {
        action
        customWhile(predicate)(action)
      }
    }

    var counter = 1
    customWhile(counter <= 10) {
      println(counter)
      counter += 1
    }
  }
}

Lazy Evaluation

Lazy evaluation delays computation until the value is actually needed.

package com.example.functions

object LazyEvaluation {
  def main(args: Array[String]): Unit = {
    def subtract(x: Int, y: Int): Int = {
      println("Executing subtraction")
      x - y
    }

    val immediate = subtract(6, 3)
    println("-" * 50)

    lazy val deferred = subtract(7, 2)
    println(deferred)
  }
}

Lazy can only be applied to val, not var.

Classes and Objects

Classes are defined using the class keyword.

package com.example.oop

object PersonExample {
  def main(args: Array[String]): Unit = {
    val person = new Person
    person.setName("Alex")
    person setAge 25

    println(person.getName)
    println(person.getAge)
    println(person.identifier)
  }
}

class Person {
  var name: String = _
  var age: Int = _
  val identifier: String = "defaultId"

  def setName(n: String): Unit = this.name = n
  def getName = this.name
  def setAge(a: Int) = this.age = a
  def getAge = this.age
}

Empty classes can omit braces.

Constructors

Scala uses primary and auxiliary constructors.

package com.example.oop

object StudentExample {
  def main(args: Array[String]): Unit = {
    val student = new Student("Ella", 16, "TechSchool")
    println(student.name)
    println(student.school)
    student.displayInfo()

    val student2 = new Student("Leo", 12, 5)
    println(student2.gradeLevel)
  }
}

class Student(var name: String, age: Int, val school: String) {
  var gradeLevel: Int = _

  def this(name: String, age: Int, grade: Int) {
    this(name, age, "TechSchool")
    this.gradeLevel = grade
  }

  def displayInfo(): Unit = println(s"Name: $name, Age: $age, School: $school")
}

Access Modifiers

Scala provides private, protected, and default public access.

package com.example.oop

class Occupation {
  val id: Long = 12865496L
  protected var department: String = _
  private var name: String = _
  private[oop] var location: String = _
}

class Instructor extends Occupation {
  def showDetails(): Unit = println(s"$id, $department")
}

Properties with Getters and Settters

package com.example.oop

object RectangleDemo {
  def main(args: Array[String]): Unit = {
    val rect = new Rectangle
    rect.height = 5.2
    println(rect.height)
    rect.width = 4.5
    println(rect.width)
    println(rect.area)
  }
}

class Rectangle {
  private var _height: Double = _
  private var _width: Double = _

  def height: Double = _height
  def height_=(h: Double): Unit = this._height = h

  def width: Double = _width
  def width_=(w: Double): Unit = this._width = w

  def area: Double = this._height * this._width
}

Packages and Imports

Packages can be defined in multiple styles.

package com.example.utils

import java.util.{ArrayList, List => JList, _}
import scala.collection.mutable.{Map => MutableMap}

object PackageExample {
  def main(args: Array[String]): Unit = {
    val list = new ArrayList[String]()
  }
}

Package Objects

Package objects allow shared definitions within a package.

package com.example.shared
package utilities

object PackageObjectDemo {
  def main(args: Array[String]): Unit = {
    println(utilities.multiply(4, 5))
    println(utilities.baseValue)
  }
}

package object utilities {
  val baseValue = 100
  def multiply(x: Int, y: Int): Int = x * y
}

Inheritance and Polymorphism

Scala supports single inheritance with extends.

package com.example.inheritance

object InheritanceExample {
  def main(args: Array[String]): Unit = {
    val learner: Learner = new Beginner
    learner.learn()
    println(learner.serialVersion)

    println(learner.isInstanceOf[Beginner])
    val beginner = learner.asInstanceOf[Beginner]
  }
}

class Learner {
  val serialVersion: Long = 54896524L
  def learn(): Unit = println("Learning")
}

class Beginner extends Learner {
  override val serialVersion: Long = 3248203578L
  override def learn(): Unit = println("Beginner is learning")
}

Tags: Scala functional-programming currying lazy-evaluation object-oriented

Posted on Thu, 17 Sep 2026 16:36:00 +0000 by donbonzo