
- Scala - Home
- Scala - Overview
- Scala - Features
- Scala - Environment Setup
- Scala - Build Tool (SBT)
- Scala - REPL
- Scala - Dot & Dotty
- Scala - Basic Syntax
- Scala - Hello World Program
- Scala - Identifiers
- Scala - Keywords
- Scala - Comments
- Scala - Code Blocks
- Scala - Semicolon
- Scala - Constructs
- Scala - Expressions
- Scala - Input and Output
- Scala - Optional Braces
- Scala - Underscore (_)
- Data Types and Variables
- Scala - Data Types
- Scala - Type Bounds
- Scala - Context Bound
- Scala - Variances
- Scala - Type Hierarchy
- Scala - Variables
- Scala - Variable Scopes
- Scala - Literals
- Scala - Numeric Types
- Scala - Boolean Types
- Scala - Char Type
- Scala - Unit Types
- Scala - Strings
- Scala - Arrays
- Scala - Null Type
- Scala - Nothing
- Scala - Any Type
- Scala - AnyRef Type
- Scala - Unified Types
- Scala - Dates and Times
- Scala - Ranges
- Scala - Multidimensional Arrays
- Scala - WrappedArray
- Scala - StringBuilder
- Scala - String Interpolation
- Scala - StringContext
- Scala - Type Casting
- Scala var vs val
- Scala Operators
- Scala - Operators
- Scala - Rules for Operators
- Scala - Arithmetic Operators
- Scala - Relational Operators
- Scala - Logical Operators
- Scala - Bitwise Operators
- Scala - Assignment Operators
- Scala - Operators Precedence
- Scala - Symbolic Operators
- Scala - Range Operator
- Scala - String Concatenation Operator
- Scala Conditional Statements
- Scala - IF ELSE
- Scala - IF-ELSE-IF-ELSE Statement
- Scala - Nested IF-ELSE Statement
- Scala Loop Statements
- Scala - Loop Statements
- Scala - while Loop
- Scala - do-while Loop
- Scala - Nested Loops
- Scala - for Loop
- Scala - break Statement
- Scala - yield Keyword
- Scala Classes & Objects
- Scala - Classes & Objects
- Scala - Constructors
- Scala - Auxiliary Constructor
- Scala - Primary Constructor
- Scala - This Keyword
- Scala - Nested Classes
- Scala - Getters and Setters
- Scala - Object Private Fields
- Scala - Singleton Object
- Scala - Companion Objects
- Scala - Creating Executable Programs
- Scala - Stateful Object
- Scala - Enumerations
- Scala - Polymorphism
- Scala - Access Modifiers
- Scala - Apply Method
- Scala - Update Methods
- Scala - UnapplySeq Method
- Scala - Inheritance
- Scala - Extending a Class
- Scala - Method Overloading
- Scala - Method Overriding
- Scala - Generic Classes
- Scala - Generic Functions
- Scala - Superclass Construction
- Scala Methods & Functions
- Scala - Functions
- Scala - Main Methods
- Scala - Functions Call-by-Name
- Scala - Functions with Named Arguments
- Scala - Function with Variable Arguments
- Scala - Recursion Functions
- Scala - Default Parameter Values
- Scala - Functions without Parameters
- Scala - Implicit Parameters
- Scala - Higher-Order Functions
- Scala - Nested Functions
- Scala - Extension Methods
- Scala - Anonymous Functions
- Partially Applied Functions
- Scala - Lazy Val
- Scala - Pure Function
- Scala - Currying Functions
- Scala - Control Abstractions
- Scala - Corecursion
- Scala - Unfold
- Scala - Tail Recursion
- Scala - Infinite Sequences
- Scala - Dynamic Invocation
- Scala - Lambda Expressions
- Scala Collections
- Scala - Collections
- Mutable and Immutable Collections
- Scala - Lists
- Scala - Sets
- Scala - Maps
- Scala - TreeMap
- Scala - SortedMap
- Scala - Tuples
- Scala - Iterators
- Scala - Options
- Scala - Infinite Streams
- Scala - Parallel Collections
- Scala - Algebraic Data Types
- Scala Pattern Matching
- Scala - Pattern Matching
- Scala - Type Patterns
- Scala - Exception Handling
- Scala - Extractors
- Scala - Regular Expressions
- Scala Files I/O
- Scala - Files I/O
- Scala Advanced Concepts
- Scala - Closures
- Scala - Futures
- Scala - Promises
- Scala - Traits
- Scala - Trait Mixins
- Scala - Layered Traits
- Scala - Trait Linearization
- Scala - Sealed Traits
- Scala - Transparent Traits
- Scala - Literal Type Arithmetic
- Scala - Inline keyword
- Scala - Def, Var & Val
- Scala - Dropped Features
- Scala - BDD Testing
Scala Functions - Call-by-Name Parameters
This chapter takes you through the concept of call-by-name parameters in Scala programming. You can delay the evaluation of an expression until it is actually used within the function. It is used where you want to defer computation and avoid unnecessary evaluations.
Call-by-Name Parameters
Functions can have parameters that are either call-by-value or call-by-name. Call-by-value parameters are evaluated before the function is executed. Whereas call-by-name parameters are evaluated each time these are accessed within the function. Call-by-name parameters are defined using the => syntax.
Definition
Call-by-name parameters in Scala are defined using the => symbol before the parameter type. So, parameters are evaluated lazily. Hence expression is not computed until it is actually referenced within the function body.
Syntax
The syntax of the call by name parameter is -
def functionName(parameterName: => Type): ReturnType = { // Function body }
Example
The following example demonstrates a simple function with a call-by-name parameter in Scala programming -
object Demo { def main(args: Array[String]) = { delayed(time()) } def time(): Long = { println("Getting time in nanoseconds") System.nanoTime() } def delayed(t: => Long): Unit = { println("In delayed method") println("Param: " + t) println("Param: " + t) } }
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
In delayed method Getting time in nanoseconds Param: <some nanosecond timestamp> Getting time in nanoseconds Param: <some nanosecond timestamp>
In the example, the time method returns the current time in nanoseconds. The delayed method takes call-by-name parameter t of type Long. The time method is called each time parameter t is accessed within the delayed method. Hence multiple evaluations occur.
Differences Between Call-by-Name and Call-by-Value
Call-by-value parameters are evaluated before the function execution begins. This method is more efficient because it avoids the repetitive re-evaluation of expressions required by call-by-name parameters. Whereas, call-by-name parameters are evaluated each time these are accessed within the function. So, this can lead to inefficiencies if the parameter is used multiple times.
- Call-by-Value: Parameters are evaluated before the function is executed.
- Call-by-Name: Parameters are evaluated each time they are accessed within the function.
Syntax Comparison
The syntax comparison of these -
// Call-by-Value def functionName(parameterName: Type): ReturnType = { // Function body } // Call-by-Name def functionName(parameterName: => Type): ReturnType = { // Function body }
Example
The following example compares call-by-value and call-by-name parameters in Scala programming -
object Demo { def main(args: Array[String]) = { println("Call-by-Value:") callByValue(time()) println("Call-by-Name:") callByName(time()) } def time(): Long = { println("Getting time in nanoseconds") System.nanoTime() } def callByValue(t: Long): Unit = { println("In callByValue method") println("Param: " + t) println("Param: " + t) } def callByName(t: => Long): Unit = { println("In callByName method") println("Param: " + t) println("Param: " + t) } }
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
Call-by-Value: Getting time in nanoseconds In callByValue method Param: <some nanosecond timestamp> Param: <some nanosecond timestamp> Call-by-Name: In callByName method Getting time in nanoseconds Param: <some nanosecond timestamp> Getting time in nanoseconds Param: <some nanosecond timestamp>
In the example, the callByValue method evaluates the time function once before executing method. So the same value is printed twice as a result. The callByName method evaluates time function every time the parameter t is accessed. So the different values are printed as a result.
Use of Call-by-Name Parameters
Call-by-name parameters have various uses, like in implementation of lazy evaluation and custom control structures. In lazy evaluation, expressions are only evaluated when their values are needed. So, it can enhance performance by deferring computation. For control structures, call-by-name, developers can create custom loops and conditionals that dictate the flow of execution based on when parameters are accessed.
1. Lazy Evaluation
Call-by-name parameters can be used to implement lazy evaluation, where expressions are only evaluated when needed.
Example
object Demo { def main(args: Array[String]) = { lazyEval(println("This will not be printed")) } def lazyEval(expr: => Unit): Unit = { println("In lazyEval method") } }
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
In lazyEval method
In the example, the lazyEval method takes a call-by-name parameter expr of type Unit. Since the parameter is never accessed within the method. So the println statement in the main method is not executed.
2. Control Structures
Custom control structures (like loops and conditionals) can be implemented using call-by-name parameters to control the flow of execution.
Example
object Demo { def main(args: Array[String]) = { loopWhile(5 > 3) { println("Looping...") } } def loopWhile(condition: => Boolean)(body: => Unit): Unit = { if (condition) { body loopWhile(condition)(body) } } }
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
Looping... Looping... Looping... ...
In the example, the loopWhile method implements custom control structure using call-by-name parameters for the condition and body of the loop. The loop executes as long as the condition is true.
Call-by-Name Parameters Summary
- Call-by-name parameters delay the evaluation of an expression until it is accessed within the function.
- Call-by-name parameters are defined using the =>
- Call-by-name parameters can be useful for lazy evaluation and implementing custom control structures.