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

Commit 761a635

Browse files
authored
Update slide deck (#124)
* Update recap chapter * Update chapter of the Scala compiler's rewriting capabilities * Update chapter on Top Level Definitions * Update chapter on Extension methods * Update chapter on given/using/summon * Update chapter on enumerations and export * Update chapter on intersection- and union types * Update chapter on opaque type aliases * Update chapter on multiversal equality
1 parent fc3fdab commit 761a635

9 files changed

+181
-149
lines changed

slides/02-recap-scala2-akka-typed-scala3.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* 2.13
1919
* Important progress on compiler performance and collections rewrite
2020
* New, binary compatible *`Vector`* implementation
21-
* Most recent release 2.13.10
21+
* Most recent release 2.13.11
2222
* 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
2323

2424
---
@@ -28,12 +28,12 @@
2828

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

3939
---

slides/04-scala3-compiler-rewrite-capabilities.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
---
3434

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

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

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

6769
---
6870

slides/05-top-level-definitions.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
## Scala 3 Top-level definitions
1313

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

9191
---
@@ -116,7 +116,7 @@ private val private_y = 730
116116
package org.lunatechlabs.multi
117117

118118
object Application extends App {
119-
println(s"$x $y $private_x $private_y)
119+
println(s"$x $y $private_x $private_y")
120120
}
121121
```
122122

@@ -126,7 +126,7 @@ object Application extends App {
126126
## &#173;
127127

128128
* In this chapter, we have taken a closer look at top-level definitions.
129-
* Package objects are now redundant and will be removed from Scala.
129+
* Package objects are now redundant and will be removed from Scala at some point in time
130130
* A source file can freely mix top-level
131131
* value
132132
* methods

slides/07-extension-methods.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414
## &#173;
1515

1616
* Scala's *implicits* enable abstraction over context
17+
### &#173;
1718
* *implicits* enables overcoming common phenomena in Functional Programming:
1819
* Writing out complex instances in full can be very cumbersome
1920
* Functions lead to long argument lists, which render code less readable and feels like boilerplate
2021
* The killer application for *implicits* are so-called Type classes
2122
* Note that using *implicits* to pass in parameters implicitly is powerful but can also be quite confusing.
22-
23+
### &#173;
24+
* 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
2325
---
2426

2527
## Contextual Abstractions - II
@@ -30,7 +32,7 @@
3032
* Adding a separate so-called *implicit parameter* list to a function
3133
* 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
3234
* In case no *implicit value* is found, the code will not compile
33-
## &#173;
35+
### &#173;
3436
* Instead of typing out complex instances in full, contextual abstractions allow one to *"summon"* such instances based on their type
3537

3638
---
@@ -188,7 +190,7 @@
188190
case (Some(d), Some(r)) => Some((d, r))
189191
case _ => None
190192

191-
import SafeDiv.*; import SafeDiv.*
193+
import SafeDiv.*
192194

193195
val d1 = 25.divide(3) // Some((8,1))
194196
val d2 = 25.divide(0) // None
@@ -263,4 +265,4 @@
263265

264266
* In this exercise we will use extension methods instead of implicit classes to add methods to our types.
265267
* Make sure you're positioned at exercise *"extension methods"*
266-
* Follow the exercise instructions provided in the README.md file in the code folder
268+
* Follow the exercise instructions provided in the README.md file in the code folder

slides/08-given-using-summon.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,14 @@
1515

1616

1717
* In the chapters on ***`extension method`***&#173;s, we mentioned abstraction over context
18-
* via ***`implicit`***&#173;s in Scala 2
19-
* via ***given*** and ***`using`*** in Scala 3
18+
* via ***`implicit`***&#173;s in Scala 2
19+
* via ***`given`*** and ***`using`*** in Scala 3
20+
#### &#173;
2021
* ***`given`*** instances define a *"canonical"* value of a certain type that can be used for synthesising arguments for context parameters (***`using`*** clauses)
21-
* 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
22+
#### &#173;
23+
* 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
2224
* This eliminates the confusion that was caused by the multiple distinctive use cases of the Scala 2 ***`implicit`*** keyword
25+
#### &#173;
2326
* When moving from Scala 2, we have the benefit to move to Scala 3's *Contextual Abstractions* in steps
2427

2528
---
@@ -97,9 +100,9 @@ startEngine(Engine("AC-35-B/002"))
97100
```
98101

99102
* The synthesised type names use the following rules:
100-
* The prefix ***given_***
101-
* The simple name(s) of the implemented type(s)
102-
* The simple name(s) of the toplevel argument type constructors to these types
103+
* The prefix ***given_***
104+
* The simple name(s) of the implemented type(s)
105+
* The simple name(s) of the toplevel argument type constructors to these types
103106

104107
---
105108

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

122126
---
@@ -237,7 +241,7 @@ val res5: Int = 3
237241
```
238242

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

243247
```scala

slides/09-enumerations-and-export.md

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414

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

2628
---
@@ -98,7 +100,8 @@ enum Planet(mass: Double, radius: Double):
98100
* Defining an explicit companion object for an enum
99101

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

228-
scala> println(s"inc.ordinal = ${inc.ordinal})
231+
scala> println(s"inc.ordinal = ${inc.ordinal}")
229232
inc.ordinal = 1
230233

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

235238
scala> conf1.<TAB> // which members are defined on this enum instance?
236-
_2 wait canEqual formatted productPrefix
237-
!= eq clone ensuring notifyAll productElement
238-
## ne equals finalize asInstanceOf productIterator
239-
-> inc notify getClass isInstanceOf productElementName
240-
== copy ordinal hashCode productArity productElementNames
241-
_1 init $ordinal toString synchronized
239+
_2 wait canEqual formatted productPrefix
240+
!= eq clone ensuring notifyAll productElement
241+
## ne equals finalize asInstanceOf productIterator
242+
-> inc notify getClass isInstanceOf productElementName
243+
== copy ordinal hashCode productArity productElementNames
244+
_1 init $ordinal toString synchronized
242245
```
243246

244247
---
245248

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

249-
* Scala 3's export clause allows us to create alias of selected members
252+
* Scala 3's export clause allows us to create aliases for selected members
250253

251254
```scala
252255
object A:
@@ -263,7 +266,7 @@ scala> A.x
263266
val res1: Int = 5
264267
```
265268

266-
* 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)
269+
* 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)
267270

268271
---
269272

slides/10-intersection-and-union-types.md

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,17 @@ trait Paintable:
5959

6060
def resizeAndPaint(obj: Growable & Paintable): Unit =
6161
obj.growBy(20).paint(0x10FF00).growBy(40).paint(0x0010FF)
62+
63+
```
64+
65+
* and using it:
6266

63-
resizeAndPaint(new Growable with Paintable)
67+
```scala
68+
scala> resizeAndPaint(new Growable with Paintable)
69+
Growing by 20%
70+
Painted with color 1113856
71+
Growing by 40%
72+
Painted with color 4351
6473
```
6574

6675
---
@@ -103,6 +112,7 @@ enum ToolSupplies:
103112
def printIt(t: Tools | ToolSupplies): Unit = t match
104113
case tool: Tools => println(s"Got a tool: $tool")
105114
case supply: ToolSupplies => println(s"Got a supply: $supply")
115+
106116
```
107117

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

126136
* The behaviour of an Actor is implemented via the ***`akka.actor.typed.Behavior`*** API
137+
#### &#173;
127138
* 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
139+
#### &#173;
128140
* 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
129-
### &#173;
141+
#### &#173;
130142
* How do we encode a behaviour so that it can process both commands and responses internally, while limiting the external protocol to ***`Command`***?
131143

132144
---
@@ -181,10 +193,11 @@ Got a supply: Nail(9)
181193
### Akka Typed Actors - encoding
182194

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

190203
---
@@ -211,6 +224,7 @@ type CommandAndResponse = Command | Response
211224
// implicitly[Behavior[CommandAndResponse] <:< Behavior[Command]]
212225
val internalBehavior: Behavior[CommandAndResponse] = new Behavior[CommandAndResponse]{}
213226
val externalBehavior: Behavior[Command] = internalBehavior // Contravariance at work
227+
214228
```
215229
```scala
216230
internalBehavior.treatMsg(Command.Reset)
@@ -220,7 +234,8 @@ internalBehavior.treatMsg(Response.RunFinished)
220234

221235
externalBehavior.treatMsg(Command.Reset)
222236
externalBehavior.treatMsg(Command.Run(110))
223-
externalBehavior.treatMsg(Response.RunFailed("Too much to do”)) // Doesn’t compile
237+
externalBehavior.treatMsg(Response.RunFailed("Too much to do")) // Doesn't compile
238+
224239
```
225240

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

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

0 commit comments

Comments
 (0)