Skip to content

Commit

Permalink
Merge branch 'wjlow:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
lukestephenson-zendesk authored Oct 6, 2023
2 parents 972f4bb + 7ec8430 commit fd19015
Show file tree
Hide file tree
Showing 23 changed files with 56 additions and 54 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,13 +166,13 @@ sbt> console
Once in the console, you can import your production code as such:

```
import package.objectname._
import package.objectname.*
```

For example, to use functions defined in _introcourse.level01.IntroExercises_:

```
scala> import introcourse.level01.IntroExercises._
scala> import introcourse.level01.IntroExercises.*
scala> add(1, 2)
res0: Int = 3
```
Expand Down
10 changes: 4 additions & 6 deletions cheat-sheet.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,16 +131,14 @@ The values of a product type typically contain several values, called fields. Fo
Values of algebraic types are analysed with pattern matching, which identifies a value by its constructor or field names and extracts the data it contains.

### Sealed trait
When defining an algebraic data type using sealed traits, it allows the compiler to exhaustively check the possible cases in match expressions.
When defining an algebraic data type using enums, it allows the compiler to exhaustively check the possible cases in match expressions.
The compiler will emit a warning (or an error is the option "-Xfatal-warnings" option is enabled) if you have missed a specific case.
The compiler knows all of the subtypes of the trait that can possibly exist as they can only be extended in the file.

```scala
sealed trait MyBooleanType

case object True extends MyBooleanType

case object False extends MyBooleanType
enum MyBooleanType {
case True, False
}
```

### Pattern matching
Expand Down
9 changes: 8 additions & 1 deletion src/main/scala/introcourse/level02/TypesExercises.scala
Original file line number Diff line number Diff line change
Expand Up @@ -175,17 +175,24 @@ object TypesExercises {
*
* You can read the following as a `TrafficLight` is either `Red` or `Yellow` or `Green`.
*
* A sealed trait can only be extended in the same file that it is defined.
* A sealed trait / enum can only be extended in the same file that it is defined.
*
* This technique helps you make invalid states/values irrepresentable in your programs
*/
enum TrafficLight {
case Red, Yellow, Green
}

// Scala 2.12 equivalent syntax
/*
sealed trait TrafficLight
case object Red extends TrafficLight
case object Yellow extends TrafficLight
case object Green extends TrafficLight
*/

/**
* scala> showTrafficLight(Red)
Expand Down
10 changes: 3 additions & 7 deletions src/main/scala/introcourse/level03/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@ package object level03 {

case class Person(name: String, age: Int)

sealed trait TrafficLight

case object Red extends TrafficLight

case object Yellow extends TrafficLight

case object Green extends TrafficLight
enum TrafficLight {
case Red, Yellow, Green
}

}
10 changes: 3 additions & 7 deletions src/main/scala/introcourse/level04/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@ package object level04 {

case class Person(name: String, age: Int)

sealed trait TrafficLight

case object Red extends TrafficLight

case object Yellow extends TrafficLight

case object Green extends TrafficLight
enum TrafficLight {
case Red, Yellow, Green
}

}
12 changes: 5 additions & 7 deletions src/main/scala/introcourse/level05/EitherExercises.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@ import ExceptionExercises.personStringPairs
object EitherExercises {

//ADT for representing errors as values
sealed trait AppError

case object EmptyName extends AppError

case class InvalidAgeValue(value: String) extends AppError

case class InvalidAgeRange(age: Int) extends AppError
enum AppError {
case EmptyName
case InvalidAgeValue(value: String)
case InvalidAgeRange(age: Int)
}

/**
* In the ExceptionExercises exercise we used Exceptions to handle validation and
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/introcourse/level06/Try.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def evenE(n: Int): Either[String, Int] = if (n % 2 == 0) Right(n) else Left (s"$
```

```scala
import scala.util._
import scala.util.*

def evenT(n: Int): Try[Int] = if (n % 2 == 0) Success(n) else Failure (new RuntimeException(s"$n is not even"))
```
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/introcourse/level06/TryExercises.scala
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ object TryExercises {
case class Employee()

/**
* Now remove `import TryTestTypes._` from `TryExercisesTest.scala`
* Now remove `import TryTestTypes.*` from `TryExercisesTest.scala`
*/

/**
Expand Down
10 changes: 7 additions & 3 deletions src/main/scala/introcourse/level07/LogParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ object LogParser {
* - Warning
* - Error with (severity: Int)
*/
sealed trait LogLevel
enum LogLevel {
case TODO // enums must have as least one case, replace this when you are ready
}

/**
* Now create an ADT for `LogMessage`, where `LogMessage` can be one of two possibilities:
Expand All @@ -44,10 +46,12 @@ object LogParser {
*/
type Timestamp = Int

sealed trait LogMessage
enum LogMessage {
case TODO // enums must have as least one case, replace this when you are ready
}

/**
* Once you have defined your data types, remove `import Types._` from
* Once you have defined your data types, remove `import Types.*` from
* [LogParserTest.scala](src/test/scala/introcourse/level07/LogParserTest.scala)
*/

Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/introcourse/level07/Main.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package introcourse.level07

import scala.io.Source
import LogParser._
import LogParser.*

/**
* The `main` method does the following:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package introcourse.level01

import introcourse.level01.IntroExercises._
import introcourse.level01.IntroExercises.*
import org.scalactic.TypeCheckedTripleEquals
import org.scalatest.funspec.AnyFunSpec

Expand Down
3 changes: 2 additions & 1 deletion src/test/scala/introcourse/level02/TypesExercisesTest.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package introcourse.level02

import introcourse.level02.TypesExercises._
import introcourse.level02.TypesExercises.*
import introcourse.level02.TypesExercises.TrafficLight.*
import org.scalactic.TypeCheckedTripleEquals
import org.scalatest.funspec.AnyFunSpec

Expand Down
2 changes: 1 addition & 1 deletion src/test/scala/introcourse/level03/ListExercisesTest.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package introcourse.level03

import introcourse.level03.ListExercises._
import introcourse.level03.ListExercises.*
import org.scalactic.TypeCheckedTripleEquals
import org.scalatest.funspec.AnyFunSpec

Expand Down
3 changes: 2 additions & 1 deletion src/test/scala/introcourse/level04/NullExercisesTest.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package introcourse.level04

import introcourse.level04.NullExercises._
import introcourse.level04.NullExercises.*
import introcourse.level04.TrafficLight.*
import org.scalactic.TypeCheckedTripleEquals
import org.scalatest.funspec.AnyFunSpec

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package introcourse.level04

import introcourse.level04.OptionExercises1._
import introcourse.level04.OptionExercises1.*
import introcourse.level04.TrafficLight.*
import org.scalactic.TypeCheckedTripleEquals
import org.scalatest.funspec.AnyFunSpec

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package introcourse.level04

import introcourse.level04.OptionExercises2._
import introcourse.level04.OptionExercises2.*
import org.scalactic.TypeCheckedTripleEquals
import org.scalatest.funspec.AnyFunSpec

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package introcourse.level04

import introcourse.level04.OptionExercises2.Job
import introcourse.level04.OptionExercises3._
import introcourse.level04.OptionExercises3.*
import org.scalactic.TypeCheckedTripleEquals
import org.scalatest.funspec.AnyFunSpec

Expand Down
3 changes: 2 additions & 1 deletion src/test/scala/introcourse/level05/EitherExercisesTest.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package introcourse.level05

import introcourse.level05.EitherExercises._
import introcourse.level05.EitherExercises.*
import introcourse.level05.EitherExercises.AppError.*
import org.scalactic.TypeCheckedTripleEquals
import org.scalatest.funspec.AnyFunSpec

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package introcourse.level05

import introcourse.level05.ExceptionExercises._
import introcourse.level05.ExceptionExercises.*
import org.scalactic.TypeCheckedTripleEquals
import org.scalatest.funspec.AnyFunSpec

Expand Down
5 changes: 2 additions & 3 deletions src/test/scala/introcourse/level06/TryExercisesTest.scala
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package introcourse.level06

import introcourse.level06.TryExercises._

import introcourse.level06.TryExercises.*
import org.scalactic.TypeCheckedTripleEquals
import org.scalatest.funspec.AnyFunSpec

import scala.util.{Failure, Success}

class TryExercisesTest extends AnyFunSpec with TypeCheckedTripleEquals {
// TODO: Remove this import once you've defined Employee data type in TryExercuses
import TryTestTypes._
import TryTestTypes.*

describe("parseIntSafe") {

Expand Down
4 changes: 2 additions & 2 deletions src/test/scala/introcourse/level06/TryTestTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package introcourse.level06

/**
* This file exists just to get the type-safe tests in `TryExercisesTest.scala` to compile.
* Once you have defined the `Employee` type in `TryExercises.scala`, remove `import TryTestTypes._`
* Once you have defined the `Employee` type in `TryExercises.scala`, remove `import TryTestTypes.*`
* from `TryExercisesTest.scala`.
*/
object TryTestTypes {
private def undefinedInTry: Nothing =
throw new RuntimeException("Please remove `import TryTestTypes._` from `TryExercisesTest.scala`")
throw new RuntimeException("Please remove `import TryTestTypes.*` from `TryExercisesTest.scala`")

def Employee(args: Any*): Nothing = undefinedInTry
}
4 changes: 2 additions & 2 deletions src/test/scala/introcourse/level07/LogParserTest.scala
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package introcourse.level07

import introcourse.level07.LogParser._
import introcourse.level07.LogParser.*
import org.scalactic.TypeCheckedTripleEquals
import org.scalatest.funspec.AnyFunSpec

class LogParserTest extends AnyFunSpec with TypeCheckedTripleEquals {
// TODO: Remove this import once you've defined the ADTs in LogParser
import Types._
import Types.*

describe("parseIntOption") {
it("should return the parsed integer for a valid integer") {
Expand Down
4 changes: 2 additions & 2 deletions src/test/scala/introcourse/level07/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package introcourse.level07

/**
* This file exists just to get the type-safe tests in `LogParserTests.scala` to compile.
* Once the ADTs are defined in `LogParser.scala`, remove `import Types._` from `LogParserTests.scala`.
* Once the ADTs are defined in `LogParser.scala`, remove `import Types.*` from `LogParserTests.scala`.
*/
object Types {
private def undefinedInLogParser: Nothing =
throw new RuntimeException("Please remove `import Types._` from `LogParserTests.scala`")
throw new RuntimeException("Please remove `import Types.*` from `LogParserTests.scala`")

def Info: Nothing = undefinedInLogParser
def Warning: Nothing = undefinedInLogParser
Expand Down

0 comments on commit fd19015

Please sign in to comment.