Skip to content

Commit

Permalink
Bump Scala version/revise samples/add scalafmt (#118)
Browse files Browse the repository at this point in the history
  • Loading branch information
eloots committed Aug 25, 2023
1 parent 21ff3e0 commit d79c35b
Show file tree
Hide file tree
Showing 25 changed files with 220 additions and 136 deletions.
51 changes: 51 additions & 0 deletions code-snippets/.scalafmt.conf
@@ -0,0 +1,51 @@
version = 3.7.2
runner.dialect = scala3

style = defaultWithAlign
indentOperator.preset = akka
maxColumn = 120
rewrite.rules = [RedundantParens, AvoidInfix]
align.tokens = [{code = "=>", owner = "Case"}]
align.openParenDefnSite = false
align.openParenCallSite = false
optIn.breakChainOnFirstMethodDot = false
optIn.configStyleArguments = false
danglingParentheses.defnSite = false
danglingParentheses.callSite = false
rewrite.neverInfix.excludeFilters = [
and
min
max
until
to
by
eq
ne
"should.*"
"contain.*"
"must.*"
in
ignore
be
taggedAs
thrownBy
synchronized
have
when
size
only
noneOf
oneElementOf
noElementsOf
atLeastOneElementOf
atMostOneElementOf
allElementsOf
inOrderElementsOf
theSameElementsAs
message
]
rewriteTokens = {
"⇒": "=>"
"→": "->"
"←": "<-"
}
14 changes: 5 additions & 9 deletions code-snippets/build.sbt
@@ -1,23 +1,19 @@

Global / onChangedBuildSource := ReloadOnSourceChanges

lazy val `scala-3-snippets` = project
.in(file("."))
.settings(ThisBuild / scalaVersion := "3.2.2")
.settings(ThisBuild / scalaVersion := "3.3.0")
.settings(
name := "dotty-simple",
version := "0.1.0",

libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test"
)
libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test")
.aggregate(
`new-control-structure-syntax`,
`contextual-abstractions`,
`intersection-and-union-types`,
`enumerations`,
`export-clause`,
`top-level-definitions`,
)
`top-level-definitions`)

lazy val `new-control-structure-syntax` = project.in(file("new-control-structure-syntax"))

Expand All @@ -27,7 +23,7 @@ lazy val `enumerations` = project.in(file("enumerations"))

lazy val `export-clause` = project.in(file("export-clause"))

lazy val `intersection-and-union-types` = project.in(file("intersection-and-union-types"))
lazy val `intersection-and-union-types` =
project.in(file("intersection-and-union-types")).settings(scalacOptions ++= Seq("-source", "future-migration"))

lazy val `top-level-definitions` = project.in(file("top-level-definitions"))

4 changes: 1 addition & 3 deletions code-snippets/contextual-abstractions/build.sbt
@@ -1,3 +1 @@
scalacOptions ++= Seq(
"-source:3.0",
)
scalacOptions ++= Seq("-source:3.0")
Expand Up @@ -2,12 +2,10 @@ package org.lunatech.dotty.multiversalequality

import java.util.UUID

/**
* In this example we imagine that we refactored 'Item' so that now we use
* UUID instead of our custom-made 'Id' value class to identify items.
* But in the refactor we forgot to change the Repository.findById.
* This will type-check but we will not find the repository
*/
/** In this example we imagine that we refactored 'Item' so that now we use UUID instead of our custom-made 'Id' value
* class to identify items. But in the refactor we forgot to change the Repository.findById. This will type-check but
* we will not find the repository
*/
object Bad1:
final case class Id(value: Long) extends AnyVal
final case class Item(id: UUID)
Expand All @@ -17,20 +15,18 @@ object Bad1:
items.find(_.id == id)
}

/**
* Same as above but now we import strictEquality in the scope. This will now
* fail to compile because we don't have any Eql typeclass instances for
* comparing 'Id' with UUID
*/
/** Same as above but now we import strictEquality in the scope. This will now fail to compile because we don't have any
* Eql typeclass instances for comparing 'Id' with UUID
*/
object Bad2:

final case class Id(value: Long) extends AnyVal
final case class Item(id: UUID)

import scala.language.strictEquality
/** COMMENTED OUT. DOES NOT COMPILE.
* For illustration purposes
*/
// class Repository(items: Seq[Item]):

/** COMMENTED OUT. DOES NOT COMPILE. For illustration purposes
*/
// class Repository(items: Seq[Item]):
// def findById(id: Id): Option[Item] =
// items.find(_.id == id) // Thus futile comparison is flagged as an error
Expand Up @@ -3,9 +3,7 @@ package org.lunatech.dotty.opaquetypes
object Scala2TypeAliases:
type Kilometres = Double
class Rocket(distanceTravelled: Kilometres):
def advance(distanceToAdvance: Kilometres): Rocket = new Rocket(
distanceTravelled + distanceToAdvance
)
def advance(distanceToAdvance: Kilometres): Rocket = new Rocket(distanceTravelled + distanceToAdvance)

type Miles = Double
class Booster():
Expand All @@ -18,19 +16,18 @@ object Scala2ClassWrappers:
case class Kilometres(value: Double)
class Rocket(distanceTravelled: Kilometres):
def advance(distanceToAdvance: Kilometres): Rocket = new Rocket(
Kilometres(distanceTravelled.value + distanceToAdvance.value)
)
Kilometres(distanceTravelled.value + distanceToAdvance.value))

case class Miles(value: Double)
class Booster() {

/** COMMENTED OUT. DOES NOT COMPILE. */

// def advanceRocket(rocket: Rocket, distanceToAdvance: Miles): Rocket = {
// // Kilometres and Miles are different types. So compiler prevents this bug
// rocket.advance(distanceToAdvance)
// }


}
end Scala2ClassWrappers

Expand Down Expand Up @@ -137,7 +134,7 @@ object Scala3OpaqueTypeAliasesDefinitions:
def toMiles: Miles = a / 1.6

extension (a: Miles)
@targetName("plusMiles")
@targetName("plusMiles")
def +(b: Miles): Miles = a + b

def toKm: Kilometres = a * 1.6
Expand All @@ -148,9 +145,7 @@ object Scala3OpaqueTypeAliasesTypeSafety:
import Scala3OpaqueTypeAliasesDefinitions._

class Rocket(distanceTravelled: Kilometres):
def advance(distanceToAdvance: Kilometres): Rocket = new Rocket(
distanceTravelled + distanceToAdvance
)
def advance(distanceToAdvance: Kilometres): Rocket = new Rocket(distanceTravelled + distanceToAdvance)

class Booster():
def advanceRocket(rocket: Rocket, distanceToAdvance: Kilometres): Rocket = {
Expand All @@ -169,17 +164,15 @@ object Scala3OpaqueTypeAliasesNoAllocations1:
export Scala3OpaqueTypeAliasesDefinitions._

class Rocket(val distanceTravelled: Kilometres):
def advance(distanceToAdvance: Kilometres): Rocket = new Rocket(
distanceTravelled + distanceToAdvance
)
def advance(distanceToAdvance: Kilometres): Rocket = new Rocket(distanceTravelled + distanceToAdvance)

type Distance = Kilometres | Miles
class Booster():
// THIS GIVES A WARNING. THE 'Kilometres' CASE IS UNREACHABLE due to erasure.
// SO WE HAVE A BUG. Any 'Kilometres' passed to this method will be multiplied by 1.6
def advanceRocket(rocket: Rocket, distanceToAdvance: Distance): Rocket = {
val distanceInKm = distanceToAdvance match {
case miles: Miles => miles.toKm
case miles: Miles => miles.toKm
case km: Kilometres => km
}
rocket.advance(distanceInKm)
Expand All @@ -202,9 +195,7 @@ object Scala3OpaqueTypeAliasesNoAllocations2:
import Scala3OpaqueTypeAliasesDefinitions._

class Rocket(val distanceTravelled: Kilometres) {
def advance(distanceToAdvance: Kilometres): Rocket = new Rocket(
distanceTravelled + distanceToAdvance
)
def advance(distanceToAdvance: Kilometres): Rocket = new Rocket(distanceTravelled + distanceToAdvance)
}

type Conversion[A] = A => Kilometres
Expand Down Expand Up @@ -239,6 +230,6 @@ object Scala3OpaqueTypeAliasesNoAllocations3:
* public static double[] distances() {
* return Scala3OpaqueTypeAliasesNoAllocations3$.MODULE$.distances();
* }
*
*
*/
val distances: Array[Kilometres] = Array(Kilometres(10)) // No allocation of Kilometres object
Expand Up @@ -3,8 +3,8 @@ package org.lunatech.dotty.using
trait Ord[T] {
def compare(x: T, y: T): Int
extension (x: T)
def < (y: T) = compare(x, y) < 0
def > (y: T) = compare(x, y) > 0
def <(y: T) = compare(x, y) < 0
def >(y: T) = compare(x, y) > 0
}

given ordInt: Ord[Int] with {
Expand All @@ -16,10 +16,10 @@ object ContextBounds {
if (x > y) x else y

// The following will still be allowed in Scala 3.0, but disallowed in 3.1
//@main def contextBoundsMain = println(max(1,3)(ordInt))
// @main def contextBoundsMain = println(max(1,3)(ordInt))

}

// If you want to explicitly pass an instance of Ord[Int], do it as follows
@main def contextBoundsMain(): Unit =
println(ContextBounds.max(1,3)(using ordInt))
@main def contextBoundsMain(): Unit =
println(ContextBounds.max(1, 3)(using ordInt))
@@ -1,3 +1,3 @@
package org.lunatech.dotty.using

final case class Engine(name: String)
final case class Engine(name: String)
@@ -1,3 +1,3 @@
package org.lunatech.dotty.using

final case class EngineConfig(initialSpeed: Int, maxSpeed: Int, label: String)
final case class EngineConfig(initialSpeed: Int, maxSpeed: Int, label: String)
Expand Up @@ -4,10 +4,7 @@ final case class RecordDev(recordType: String)
final case class PlayerDev(playerType: String)

object MultipleUsingClauses {
def recordAndMonitor(recordGain: Int)
(using recordDev: RecordDev)
(volume: Int = 3)
(using player: PlayerDev) = {
def recordAndMonitor(recordGain: Int)(using recordDev: RecordDev)(volume: Int = 3)(using player: PlayerDev) = {
println(s"Recording with gain $recordGain from $recordDev to $player with volume $volume")
}

Expand All @@ -27,8 +24,8 @@ object MultipleUsingClauses2 {
opaque type Mul = Int
opaque type Add = Int

object Mul { def apply(n: Int): Mul = n}
object Add { def apply(n: Int): Add = n}
object Mul { def apply(n: Int): Mul = n }
object Add { def apply(n: Int): Add = n }

import scala.annotation.targetName

Expand All @@ -39,7 +36,7 @@ object MultipleUsingClauses2 {
extension (a: Add)
@targetName("addAsInt")
def asInt: Int = a

@main def MUC_1: Unit = {
val r = 5
println(r)
Expand All @@ -57,4 +54,4 @@ object Use {
val r = 10 * summon[Mul].asInt + summon[Add].asInt
println(r)
}
}
}
Expand Up @@ -12,7 +12,7 @@ object Scala2Example {
@main def CA_0: Unit = {
startEngine(Engine("AC-35-B/002"))
}

}

object MovingToDotty_1 {
Expand All @@ -25,7 +25,7 @@ object MovingToDotty_1 {
@main def CA_1: Unit = {
startEngine(Engine("AC-35-B/002"))
}

}

object MovingToDotty_2 {
Expand All @@ -38,5 +38,5 @@ object MovingToDotty_2 {
@main def CA_2: Unit = {
startEngine(Engine("AC-35-B/002"))
}
}

}
Expand Up @@ -10,7 +10,7 @@ object SomeActor {
}
export Command._

//def apply(): Behavior[Command] = ???
// def apply(): Behavior[Command] = ???
}

// someActor ! SomeActor.Command.Execute(5)
// someActor ! SomeActor.Command.Execute(5)
@@ -1,39 +1,39 @@
package org.lunatech.dotty.enumeration

@main def enumMemberVisibilityDefault = {

enum Command {
case Reset
case IncrementBy(inc: Int)
case Configure(init: Int, inc: Int)
}

val reset = Command.Reset // `reset` is a singleton case mapped to a val definition
val inc = Command.IncrementBy(2) // `inc` is NOT a case class
val reset = Command.Reset // `reset` is a singleton case mapped to a val definition
val inc = Command.IncrementBy(2) // `inc` is NOT a case class

val r1 = Command.Reset
val r2 = Command.Reset

println(r1 eq r2) // will print `true`
println(r1 eq r2) // will print `true`
println(s"reset.ordinal = ${reset.ordinal}") // will print reset.ordinal = 0
println(s"inc.ordinal = ${inc.ordinal}")

}

@main def enumMemberVisibility = {

enum Command {
case Reset
case IncrementBy(inc: Int)
case Configure(init: Int, inc: Int)
}

val inc = new Command.IncrementBy(2) // `inc` IS a case class
val conf = new Command.Configure(0, 5) // `conf` IS a case class
val inc = new Command.IncrementBy(2) // `inc` IS a case class
val conf = new Command.Configure(0, 5) // `conf` IS a case class

println(s"inc.ordinal = ${inc.ordinal}")
println(s"conf = $conf") // will print Configure(0, 5)
println(s"conf = $conf") // will print Configure(0, 5)
val conf1 = conf.copy(inc = 7)
println(s"conf1 = $conf1") // will print Configure(0, 7)
conf1 // which members are defined on this enum instance?
println(s"conf1 = $conf1") // will print Configure(0, 7)
conf1 // which members are defined on this enum instance?
}

0 comments on commit d79c35b

Please sign in to comment.