Last active
September 13, 2018 12:59
-
-
Save rcoh/4992969 to your computer and use it in GitHub Desktop.
Scala patterns for compiler construction
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Useful Scala Patterns for Compiler Design | |
// 1. Case Classes | |
// [For full details, see Programming in Scala 2ed, page 310] | |
// Case classes are syntactic sugar around normal Scala classes. They come prebaked with the following properties: | |
// * Factory constructor (don't need new) : | |
case class Foo(bar: String) | |
// If not case class, val x = new Foo("s") | |
val x = Foo("s") | |
// * All properties are promoted to become immutable fields. | |
// s = "s" | |
val s = Foo.bar | |
// Compiler error: can't assign to val | |
x.s = "3" | |
// * Proper definition of hashCode, Equals and toString: | |
val y = Foo("s") | |
// True | |
val same = y == x | |
// Under the hood, case classes are Products. You can use this property to operate on them in a general way if you so desire. | |
// Case Classes can be a useful representation of your IR. | |
// 2. Pattern Matching | |
val x = "123" | |
// The compiler properly infers that z must be an int. | |
val z = x match { | |
case "456" => 1 | |
case "123" => 2 | |
} | |
sealed abstract class Vehicle | |
case class Plane(numSeats: Int, maxSpeed: Int) extends Vehicle | |
case class Car(numSeats: Int, mpg: Double) extends Vehicle | |
case class Boat(numHp: Int) | |
def drive(v: Vehicle) { | |
// Pattern matching can easily extract attributes from case classes | |
// Note: Bound attributes are positional, NOT by name. | |
v match { | |
case Plane(numSeats, maxSpeed) => { println(numSeats, maxSpeed) } | |
case Car(numSeats, mpg) => { println(numSeats, mpg)} | |
case Boat(numHp) => { println(numHp) } | |
} | |
} | |
// Because vehicle is sealed, the compiler knows exactly what subclasses it has. | |
// Failure to include a subclass in a match is a compiler error: | |
def nodrive(v: Vehicle) { | |
// Compiler Error: Match not exhaustive | |
v match { | |
case Plane(numSeats, maxSpeed) => { println(numSeats, maxSpeed) } | |
} | |
} | |
// Use _ for wildcard matching | |
def alldrive(v: Vehicle) { | |
v match { | |
case Plane(_, _) => println("It's a plane") | |
case _ => { println("Something else")} | |
} | |
} | |
// Pattern matching options: | |
// Match plane objects and bind them to p. | |
case p: Plane => { ... } | |
// Extract attributes from case class, bind them to variable names or _ (don't care) | |
case Plane(numSeats, _) => { ... } | |
// Extract attributes and capture their container | |
case p@Plane(_, maxSpeed) => { ... } | |
// Pattern matching is an extremely powerful pattern that deserves some | |
// research. | |
// 3. Partial Functions | |
// A partial function allows you to encapsulate a match expression in a | |
// variable. | |
val is5: PartialFunction[Int, Boolean] = { | |
case 5 => true | |
caes _ => false | |
} | |
// False | |
val res = is5(10) | |
// The partial function library allows a lot of useful operations on partial functions: | |
// [http://www.scala-lang.org/api/current/index.html#scala.PartialFunction] | |
// Partial functions have a nice shorthand: | |
val is5: Int => Boolean = { | |
case 5 => true | |
case _ => false | |
} | |
// Partial functions are PARTIAL. Calling them with an argument they are not defined for yields a runtime error: | |
val strictIs5: Int => Boolean = { | |
case 5 => true | |
} | |
// Throws match error | |
strictIs5(10) | |
strictIs5(10) | |
// 4. Type Aliasing | |
// It can be annoying to type PartialFunction[Int, Boolean] all the time. We | |
// can alias it to a pithier type: | |
type Matcher = PartialFunction[Int, Boolean] | |
// Warning: | |
// Using the "return" keyword inside of a partial function will return from the calling function! You've been warned. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment