Code Examples for

Programming in Scala, Fifth Edition

Return to chapter index

19 Enums

Sample run of chapter's interpreter examples

19.1 Enumerated data types


// In file enums-and-adts/direction-1.scala enum Direction: case North, East, South, West
// In file enums-and-adts/invert.scala import Direction.{North, South, East, West} def invert(dir: Direction): Direction = dir match case North => South case East => West case South => North case West => East
// In file enums-and-adts/invert.scala invert(North) // South invert(East) // West
// In file enums-and-adts/direction-1.scala North.ordinal // 0 East.ordinal // 1 South.ordinal // 2 West.ordinal // 3
// In file enums-and-adts/direction-1.scala Direction.values // Array(North, East, South, West)
// In file enums-and-adts/direction-1.scala Direction.valueOf("North") // North Direction.valueOf("East") // East Direction.valueOf("Up") // IllegalArgumentException: enum case not found: Up
// In file enums-and-adts/direction-2.scala enum Direction(val degrees: Int): case North extends Direction(0) case East extends Direction(90) case South extends Direction(180) case West extends Direction(270)
// In file enums-and-adts/direction-2.scala import Direction.* North.degrees // 0 South.degrees // 180
// In file enums-and-adts/direction-3.scala enum Direction(val degrees: Int): def invert: Direction = this match case North => South case East => West case South => North case West => East case North extends Direction(0) case East extends Direction(90) case South extends Direction(180) case West extends Direction(270)
// In file enums-and-adts/direction-3.scala North.invert // South East.invert // West
// In file enums-and-adts/direction-3.scala object Direction: def nearestTo(degrees: Int): Direction = val rem = degrees % 360 val angle = if rem < 0 then rem + 360 else rem val (ne, se, sw, nw) = (45, 135, 225, 315) angle match case a if a > nw || a <= ne => North case a if a > ne && a <= se => East case a if a > se && a <= sw => South case a if a > sw && a <= nw => West
// In file enums-and-adts/direction-3.scala def allButNearest(degrees: Int): List[Direction] = val nearest = Direction.nearestTo(degrees) Direction.values.toList.filter(_ != nearest)
// In file enums-and-adts/direction-3.scala allButNearest(42) // List(East, South, West)
// In file enums-and-adts/java-direction.scala enum Direction extends java.lang.Enum[Direction]: case North, East, South, West
// In file enums-and-adts/java-direction.scala Direction.East.compareTo(Direction.South) // -1

19.2 Algebraic data types


// In file enums-and-adts/eastwood-1.scala enum Eastwood[+G, +B]: case Good(g: G) case Bad(b: B) case Ugly(ex: Throwable)
// In file enums-and-adts/eastwood-2.scala enum Eastwood[+G, +B]: def map[G2](f: G => G2): Eastwood[G2, B] = this match case Good(g) => Good(f(g)) case Bad(b) => Bad(b) case Ugly(ex) => Ugly(ex) case Good(g: G) case Bad(b: B) case Ugly(ex: Throwable)
// In file enums-and-adts/eastwood-2.scala val eastWood = Good(41) eastWood.map(n => n + 1) // Good(42)
// In file enums-and-adts/eastwood-3.scala // Generated sealed trait (the "enum type") sealed trait Eastwood[+G, +B] object Eastwood: // Generated companion object // Generated case classes case class Good[+G, +B](g: G) extends Eastwood[G, B] case class Bad[+G, +B](b: B) extends Eastwood[G, B] case class Ugly[+G, +B](ex: Throwable) extends Eastwood[G, B]
scala> Good(42) val res0: Eastwood[Int, Nothing] = Good(42) scala> Bad("oops") val res1: Eastwood[Nothing, String] = Bad(oops) scala> Ugly(new Exception) val res2: Eastwood[Nothing, Nothing] = Ugly(java.lang.Exception)
// In file enums-and-adts/seinlfeld.scala enum Seinfeld[+E]: def ::[E2 >: E](o: E2): Seinfeld[E2] = Yada(o, this) case Yada(head: E, tail: Seinfeld[E]) case Nada
scala> val xs = 1 :: 2 :: 3 :: Nada val xs: Seinfeld[Int] = Yada(1,Yada(2,Yada(3,Nada)))

19.3 Generalized ADTs


// In file enums-and-adts/literal.scala enum Literal[T]: case IntLit(value: Int) extends Literal[Int] case LongLit(value: Long) extends Literal[Long] case CharLit(value: Char) extends Literal[Char] case FloatLit(value: Float) extends Literal[Float] case DoubleLit(value: Double) extends Literal[Double] case BooleanLit(value: Boolean) extends Literal[Boolean] case StringLit(value: String) extends Literal[String]
// In file enums-and-adts/literal.scala import Literal.* def valueOfLiteral[T](lit: Literal[T]): T = lit match case IntLit(n) => n case LongLit(m) => m case CharLit(c) => c case FloatLit(f) => f case DoubleLit(d) => d case BooleanLit(b) => b case StringLit(s) => s
// In file enums-and-adts/literal.scala valueOfLiteral(BooleanLit(true)) // true: Boolean valueOfLiteral(IntLit(42)) // 42: Int

19.4 What makes ADTs algebraic


// In file enums-and-adts/traffic-light.scala enum TrafficLight: case Red, Yellow, Green
// In file enums-and-adts/hope.scala enum Hope[+T]: case Glad(o: T) case Sad
// In file enums-and-adts/both.scala case class Both[A, B](a: A, b: B)

19.5 Conclusion

For more information about Programming in Scala, Fifth Edition (the "Stairway Book"), please visit:

http://www.artima.com/shop/programming_in_scala_5ed

and:

http://booksites.artima.com/programming_in_scala_5ed

Copyright © 2007-2020 Artima, Inc. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.