Skip to content
This repository was archived by the owner on Mar 27, 2025. It is now read-only.

Update slide deck #124

Merged
merged 9 commits into from
Sep 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions slides/02-recap-scala2-akka-typed-scala3.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* 2.13
* Important progress on compiler performance and collections rewrite
* New, binary compatible *`Vector`* implementation
* Most recent release 2.13.10
* Most recent release 2.13.11
* Allow, under some restrictions to use Scala 3 libraries in Scala 2 code (using Tasty) and vice-versa. See the [Compatibility Reference pages](https://docs.scala-lang.org/scala3/guides/migration/compatibility-intro.html) in the Scala 3 Migration Guide

---
Expand All @@ -28,12 +28,12 @@

* Dotty 0.21.0-RC1: feature complete for Scala 3 (December 2019)
* 3.0.0 released on May 13, 2021
* Current release 3.2.2 released on February 1st, 2023
* Tooling - Status
* Metals:
* Current [release 3.3.0](https://github.com/lampepfl/dotty/releases/tag/3.3.0) released on May 30th, 2023
* IDE support
* [Visual Studio Code](https://code.visualstudio.com) with [Metals](https://scalameta.org/metals/)
* integrated support in Metals including Scala Worksheet support!
* IntelliJ
* Scala 3 support in Scala Plugin
* [IntelliJ](https://www.jetbrains.com/idea/)
* Scala 3 support with the [Scala Plugin](https://lp.jetbrains.com/intellij-scala/)
* There's the [Scala 3 Migration Guide](https://docs.scala-lang.org/scala3/guides/migration/compatibility-intro.html)!

---
Expand Down
12 changes: 7 additions & 5 deletions slides/04-scala3-compiler-rewrite-capabilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

---

## Rewriting of deprecated syntax - I
## Rewriting of deprecated syntax - II
* The Scala 3 compiler has a number of options that can automatically rewrite some deprecated language features
* There's a strategy defining how language features will be phased in and out after the Scala 3.0 release
* Scala 3.0
Expand All @@ -41,6 +41,8 @@
* Scala 3.x (x >= 1)
* Support of Scala 3.0 syntax which introduced new deprecations
* Rewrite of these via the ***-rewrite -source:future-migration*** compile options
* Use the [***Scala 3 Migrate sbt plugin***](https://github.com/scalacenter/scala3-migrate)
* Learn how to use it by following the [***Scala 3 Migration Course***](https://github.com/scalacenter/scala3-migration-course)

---
<!-- .slide: data-background-color="#94aabb" data-background-image="images/bg-reveal.ps.png" -->
Expand All @@ -57,12 +59,12 @@
## &#173;

* Scala 3 introduces a number of syntax changes for Scala 2 language constructs such as
* Contextual Abstractions (implicits)
* Extension methods
* [***Contextual Abstractions***](https://dotty.epfl.ch/docs/reference/contextual/index.html) (implicits)
* [***Extension methods***](https://dotty.epfl.ch/docs/reference/contextual/extension-methods.html)
* ...
* Two other notable syntax changes
* New Control Syntax (opt-in)
* "Fewer Braces" syntax: indentation is significant
* [***New Control Syntax***](https://dotty.epfl.ch/docs/reference/other-new-features/control-syntax.html) (opt-in)
* [***Optional Braces syntax***](https://dotty.epfl.ch/docs/reference/other-new-features/indentation.html) - indentation is significant

---

Expand Down
8 changes: 4 additions & 4 deletions slides/05-top-level-definitions.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
## Scala 3 Top-level definitions

* In Scala 2:
* The source code for a package object is usually put in a separate file called ***`package.scala`***
* The source code for a package object is put in a separate file named ***`package.scala`***
* Each package is allowed to have only one package object
* Any definitions placed inside a package object are considered members of the package itself
* ***`type`***, ***`def`***, and ***`val`*** definitions have to be put in an ***`object`***, ***`class`***, or ***`trait`***
Expand Down Expand Up @@ -85,7 +85,7 @@ def greetPerson(person: Person): Unit =
* The compiler generates synthetic objects to wrap top-level definitions
* In the above example, the contents of the source file ***`ToplevelDefinitions.scala`*** will be put in a synthetic object named ***`ToplevelDefinitions$package
`***
* *Top-level definitions don't have the ability to inherit from another ***`trait`*** or ***`class`*** as we could do with ***`package object`***&#173;*s*
* Top-level definitions don't have the ability to inherit from another ***`trait`*** or ***`class`*** as we could do with ***`package object`***&#173;*s*
* *A workaround for this is to use a regular object and import all needed members*

---
Expand Down Expand Up @@ -116,7 +116,7 @@ private val private_y = 730
package org.lunatechlabs.multi

object Application extends App {
println(s"$x $y $private_x $private_y)
println(s"$x $y $private_x $private_y")
}
```

Expand All @@ -126,7 +126,7 @@ object Application extends App {
## &#173;

* In this chapter, we have taken a closer look at top-level definitions.
* Package objects are now redundant and will be removed from Scala.
* Package objects are now redundant and will be removed from Scala at some point in time
* A source file can freely mix top-level
* value
* methods
Expand Down
10 changes: 6 additions & 4 deletions slides/07-extension-methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
## &#173;

* Scala's *implicits* enable abstraction over context
### &#173;
* *implicits* enables overcoming common phenomena in Functional Programming:
* Writing out complex instances in full can be very cumbersome
* Functions lead to long argument lists, which render code less readable and feels like boilerplate
* The killer application for *implicits* are so-called Type classes
* Note that using *implicits* to pass in parameters implicitly is powerful but can also be quite confusing.

### &#173;
* Caveat: *implicits* may make things a bit to easy to ignore. A good example of this is the availability of a global execution context in the Scala Runtime environment
---

## Contextual Abstractions - II
Expand All @@ -30,7 +32,7 @@
* Adding a separate so-called *implicit parameter* list to a function
* When such a function is called, the compiler will look-up the *implicit value *in scope (applying various scoping rules) and pass it to the function
* In case no *implicit value* is found, the code will not compile
## &#173;
### &#173;
* Instead of typing out complex instances in full, contextual abstractions allow one to *"summon"* such instances based on their type

---
Expand Down Expand Up @@ -188,7 +190,7 @@
case (Some(d), Some(r)) => Some((d, r))
case _ => None

import SafeDiv.*; import SafeDiv.*
import SafeDiv.*

val d1 = 25.divide(3) // Some((8,1))
val d2 = 25.divide(0) // None
Expand Down Expand Up @@ -263,4 +265,4 @@

* In this exercise we will use extension methods instead of implicit classes to add methods to our types.
* Make sure you're positioned at exercise *"extension methods"*
* Follow the exercise instructions provided in the README.md file in the code folder
* Follow the exercise instructions provided in the README.md file in the code folder
18 changes: 11 additions & 7 deletions slides/08-given-using-summon.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@


* In the chapters on ***`extension method`***&#173;s, we mentioned abstraction over context
* via ***`implicit`***&#173;s in Scala 2
* via ***given*** and ***`using`*** in Scala 3
* via ***`implicit`***&#173;s in Scala 2
* via ***`given`*** and ***`using`*** in Scala 3
#### &#173;
* ***`given`*** instances define a *"canonical"* value of a certain type that can be used for synthesising arguments for context parameters (***`using`*** clauses)
* The introduction of the new keywords given and using allow us to make a clear distinction between the <ins>definition</ins> of *"canonical"* values and the actual <ins>use</ins> of them
#### &#173;
* The introduction of the new keywords ***`given`*** and ***`using`*** allows us to make a clear distinction between the <ins>definition</ins> of *"canonical"* values and the actual <ins>use</ins> of them
* This eliminates the confusion that was caused by the multiple distinctive use cases of the Scala 2 ***`implicit`*** keyword
#### &#173;
* When moving from Scala 2, we have the benefit to move to Scala 3's *Contextual Abstractions* in steps

---
Expand Down Expand Up @@ -97,9 +100,9 @@ startEngine(Engine("AC-35-B/002"))
```

* The synthesised type names use the following rules:
* The prefix ***given_***
* The simple name(s) of the implemented type(s)
* The simple name(s) of the toplevel argument type constructors to these types
* The prefix ***given_***
* The simple name(s) of the implemented type(s)
* The simple name(s) of the toplevel argument type constructors to these types

---

Expand All @@ -117,6 +120,7 @@ def startEngine(engine: Engine)(using config: EngineConfig): Unit =
* We have:
* A [single] regular parameter list with a single parameter
* A [single] ***`using`*** clause with a single context parameter
#### &#173;
* Scala 3 allows for more than one using clause. Let's have a look at this

---
Expand Down Expand Up @@ -237,7 +241,7 @@ val res5: Int = 3
```

* Context bounds in Scala 3 maps to old-style implicit parameters in Scala 3.0 to ease the migration.
* From Scala 3.1 onwards, they will map to context clauses instead.
* From Scala 3.1 onwards, they will map to using clauses instead.
* It means, the following will still be allowed in Scala 3.0, but generate a warning in later versions

```scala
Expand Down
27 changes: 15 additions & 12 deletions slides/09-enumerations-and-export.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@

* Scala 2 has ***`Enumerations`***
* Their implementation is awkward for even simple use-cases such as defining a finite number of user-defined elements
### &#173;
#### &#173;
* Scala 3 adds the new and versatile ***`enum`*** construct which is syntactic sugar
#### &#173;
* The design of ***`enum`*** meets the following objectives:
* Allow for a concise expression and efficient definition of enumerations
* Allow the modelling of Java enumerations as Scala enumerations
* Allow for a concise expression of ADTs
* Support of all idioms expressible with case classes
#### &#173;
* Let's have a short look at each of them

---
Expand Down Expand Up @@ -98,7 +100,8 @@ enum Planet(mass: Double, radius: Double):
* Defining an explicit companion object for an enum

```scala
object Planet:
object Planets:
import Planet.*
val earthWeight = 1.0
val mass = earthWeight / Earth.surfaceGravity
val weightOnPlanets =
Expand Down Expand Up @@ -204,7 +207,7 @@ scala> val reset = Command.Reset // `reset` is a singleton case mapped t
scala> println(r1 eq r2)
true
scala> inc.<TAB> // which members are defined on this enum instance?
-> ne equals $ordinal getClass formatted isInstanceOf
-> ne equals $ordinal getClass formatted isInstanceOf
!= == wait notify ensuring hashCode notifyAll synchronized
## eq clone ordinal finalize toString asInstanceOf
```
Expand All @@ -225,28 +228,28 @@ scala> enum Command:
scala> val inc = new Command.IncrementBy(2) // `inc` IS a case class
val conf = new Command.Configure(0, 5) // `conf` IS a case class

scala> println(s"inc.ordinal = ${inc.ordinal})
scala> println(s"inc.ordinal = ${inc.ordinal}")
inc.ordinal = 1

scala> val conf1 = conf.copy(inc = 7)
println(conf1) // will print Configure(0, 7)
Configure(0,7)

scala> conf1.<TAB> // which members are defined on this enum instance?
_2 wait canEqual formatted productPrefix
!= eq clone ensuring notifyAll productElement
## ne equals finalize asInstanceOf productIterator
-> inc notify getClass isInstanceOf productElementName
== copy ordinal hashCode productArity productElementNames
_1 init $ordinal toString synchronized
_2 wait canEqual formatted productPrefix
!= eq clone ensuring notifyAll productElement
## ne equals finalize asInstanceOf productIterator
-> inc notify getClass isInstanceOf productElementName
== copy ordinal hashCode productArity productElementNames
_1 init $ordinal toString synchronized
```

---

## Scala 3's ***`export`*** clause - I
## &#173;

* Scala 3's export clause allows us to create alias of selected members
* Scala 3's export clause allows us to create aliases for selected members

```scala
object A:
Expand All @@ -263,7 +266,7 @@ scala> A.x
val res1: Int = 5
```

* We have only scratched the surface of the ***`export`*** clause. It enables us to compose new functionality rather than going through OOP's inheritance based approach. More details on this in the ***`export`*** [reference documentation](https://dotty.epfl.ch/docs/reference/other-new-features/export.html)
* We have only scratched the surface of the ***`export`*** clause. It enables us to compose new functionality rather than going through OOP's inheritance based approach. More details on this in the ***`export`*** [***reference documentation***](https://dotty.epfl.ch/docs/reference/other-new-features/export.html)

---

Expand Down
27 changes: 21 additions & 6 deletions slides/10-intersection-and-union-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,17 @@ trait Paintable:

def resizeAndPaint(obj: Growable & Paintable): Unit =
obj.growBy(20).paint(0x10FF00).growBy(40).paint(0x0010FF)

```

* and using it:

resizeAndPaint(new Growable with Paintable)
```scala
scala> resizeAndPaint(new Growable with Paintable)
Growing by 20%
Painted with color 1113856
Growing by 40%
Painted with color 4351
```

---
Expand Down Expand Up @@ -103,6 +112,7 @@ enum ToolSupplies:
def printIt(t: Tools | ToolSupplies): Unit = t match
case tool: Tools => println(s"Got a tool: $tool")
case supply: ToolSupplies => println(s"Got a supply: $supply")

```

* and using it:
Expand All @@ -124,9 +134,11 @@ Got a supply: Nail(9)
## &#173;

* The behaviour of an Actor is implemented via the ***`akka.actor.typed.Behavior`*** API
#### &#173;
* The ***`Behavior`*** takes a type parameter which corresponds to the message types the ***`Behavior`*** can and will handle as formally defined in its ***`Command`*** protocol
#### &#173;
* On top of the commands an Actor can process, it will also have to process Responses from other Actors as defined in the latter's ***`Response`*** protocol
### &#173;
#### &#173;
* How do we encode a behaviour so that it can process both commands and responses internally, while limiting the external protocol to ***`Command`***?

---
Expand Down Expand Up @@ -181,10 +193,11 @@ Got a supply: Nail(9)
### Akka Typed Actors - encoding

* Message adapters with Response wrappers solve the issue, but
* this adds quite a bit of boilerplate
* this is quite convoluted and it adds a lot of boilerplate
* requires an extra effort from anyone trying to understand the code
### &#173;
#### &#173;
* There is a better solution using Scala 3's ***`Union`*** Types!
#### &#173;
* Let's explore that

---
Expand All @@ -211,6 +224,7 @@ type CommandAndResponse = Command | Response
// implicitly[Behavior[CommandAndResponse] <:< Behavior[Command]]
val internalBehavior: Behavior[CommandAndResponse] = new Behavior[CommandAndResponse]{}
val externalBehavior: Behavior[Command] = internalBehavior // Contravariance at work

```
```scala
internalBehavior.treatMsg(Command.Reset)
Expand All @@ -220,7 +234,8 @@ internalBehavior.treatMsg(Response.RunFinished)

externalBehavior.treatMsg(Command.Reset)
externalBehavior.treatMsg(Command.Run(110))
externalBehavior.treatMsg(Response.RunFailed("Too much to do”)) // Doesn’t compile
externalBehavior.treatMsg(Response.RunFailed("Too much to do")) // Doesn't compile

```

---
Expand All @@ -244,4 +259,4 @@ externalBehavior.treatMsg(Response.RunFailed("Too much to do”)) // Doesn’t

* In this exercise, we will utilise ***`Union Types`*** to vastly simplify the handling of responses to messages sent by an Akka actor
* Make sure you're positioned at exercise *"union types"*
* Follow the exercise instructions provided in the README.md file in the code folder
* Follow the exercise instructions provided in the README.md file in the code folder
Loading