Interlude - Scala¶
What is Scala?¶
Scala is a hybrid programming language running on the Java Virtual Machine (JVM) that combines two major paradigms:
- Object Oriented: Every value is an object, including primitives like Ints.
- Functional: Every function is a value, meaning functions can be passed around just like data.
- Key Concept: Even methods are considered values in Scala.
Syntax Basics¶
- Printing: Uses
println("...")for standard output.- Feature: If you provide multiple arguments to
println(1, 2, 3), Scala automatically treats them as a tuple and prints them in parentheses(1, 2, 3). - Formatting:
printfis available for C-style formatting (e.g.,%dfor integers).
- Feature: If you provide multiple arguments to
- String Interpolation: Allows you to embed variables directly into strings.
- Usage: Prefix the string with
sorf. - Example:
s"Value is ${2+2}"evaluates to "Value is 4". - Syntax: Braces
{}are optional if the expression is a simple variable (e.g.,$x), but required for expressions.
- Usage: Prefix the string with
Variables: var vs val¶
Scala makes a strict distinction between the reference (the pointer) and the object (the data).
var(Variable): A mutable reference. You can change where this name points to (e.g.,x = 5, thenx = 6).val(Value): An immutable reference. Once assigned, this name effectively becomes a constant pointer.
Critical Conceptual Distinctions:
valreference to Mutable Object: You cannot point thevalto a new object, but you can modify the internals of the object it points to (e.g., adding an item to a mutable list).varreference to Immutable Object: You cannot change the object itself (because it is immutable), but you can make thevarpoint to a completely different object (e.g.,xpointed to3, now it points to4).
Collections: Arrays¶
- Syntax: Defined using square brackets
Array[Int], unlike Java's<Int>. - Mixed Types:
Array[Any]can hold mixed types (e.g., Integers and Doubles) becauseAnyis the universal supertype in Scala. - Operators (Immutability):
++: Concatenates two arrays to create a new array.:+: Appends a single value to create a new array.- Note: Since arrays have a fixed size, these operators never modify the original array; they always return a new copy. Attempting
+=on a standard array will fail unless you are reassigning avar.
Collections: Maps¶
Scala provides two distinct types of Maps, and it is crucial to know which one you are using.
Immutable Map (The Default)
- Creation:
Map("key" -> value). - Behavior: You cannot modify the object.
-
Updating Strategy: To "add" an item, you must use a
varreference.var m = Map("a" -> 1) m += ("b" -> 2)- Explanation: This
+=is syntactic sugar form = m + pair. It creates a new map containing the old data plus the new pair, and reassignsmto point to it. - Efficiency (Trie): Creating a "new" immutable map is actually very fast (\(O(h)\)). It uses a "Trie" (tree) structure where the new map shares most of the structure of the old map, rather than copying all data. It avoids tree rotations.
- Explanation: This
Mutable Map
- Creation:
scala.collection.mutable.Map(...). - Behavior: You can modify the object in place.
-
Updating Strategy: You can use a
valreference.val m = mutable.Map("a" -> 1) m += ("b" -> 2)- Explanation: This calls the actual
+=method defined on the object, which mutates the existing data structure in memory.
- Explanation: This calls the actual
Loops¶
Loops in Scala are expressions, meaning they can evaluate to a value.
- Ranges:
1 to 10: Inclusive (1, 2, ... 10).0 until 10: Exclusive (0, 1, ... 9).by: Sets the step size (e.g.,by 2orby -1).
- Yield (Functional Looping):
- Placing the keyword
yieldafter a loop definition turns it into a transformation (map). - Result: It returns a new collection (like a Vector) containing the results of each iteration.
- Placing the keyword
- Iterating Maps:
- You can unpack keys and values directly in the loop syntax:
for ((k, v) <- map) ....
- You can unpack keys and values directly in the loop syntax:
Functions¶
- Definition:
def name(param: Type): ReturnType = { body }. - Return Values: The
returnkeyword is optional. The result of the last expression in the block is automatically returned. - Unit Type: The Scala equivalent of
void. It represents the absence of a value (e.g., for functions that just print to the screen).
Anonymous Functions (Lambdas)
- Syntax:
(x: Int) => x * x. - Underscore Syntax: A concise shorthand for lambdas where parameters are used only once.
- Example:
List(1, 2, 3).map(_ + 1) - Meaning: The
_stands in for the parameterx => x + 1. - Order: The first
_is the first parameter, the second_is the second, etc..
- Example:
Pattern Matching (match)¶
A powerful control structure that goes far beyond a C-style switch. It can match:
- Values:
case 1 => "One" - Types:
case s: String => s(Matches if the input is a String) - Structures:
case List(y) => y(Matches if the input is a List containing exactly one element). - Note: The slides use a "Discworld Trolls" analogy (counting "1, 2, 3, many, lots") to illustrate falling through cases.
Option Type (Option, Some, None)¶
Scala's type-safe alternative to null pointers. An Option[T] is a container that holds either:
Some(value): The value exists.None: The value is missing.- Retrieving Values:
.get: Returns the value or throws an exception ifNone(unsafe).-
Pattern Matching: The preferred way to handle Options safely:
opt match { case Some(x) => x + 1 case None => 0 }
Java Interoperability¶
Scala runs on the JVM and can use standard Java libraries, but Java collections (like ArrayList) do not natively work with Scala's for loops or higher-order functions.
- The Solution: Use
JavaConverters. - Step 1:
import scala.collection.JavaConverters._ - Step 2: Call
.asScalaon any Java collection to convert it into a Scala-compatible iterator or collection.