Scala
Homepage / Notes / Computer Science / Programming Languages / Scala
Setup
Coursier
The recommended way to install Scala and other tools (Ammonite
, SBT
…)
Ammonite
Modernized Scala REPL
https://ammonite.io/#RunningAmmoniteREPL
Scala Scripts
https://ammonite.io/#ScalaScripts
org-babel
In Doom Emacs, use amm
(Ammonite) in #+begin_src
code blocks and not scala
Make sure to have a ~/.ammonite/predef.sc
file present
Language Features
Basics
println("hello, world!")
hello, world!
Strings
Concatenation
println("This is " + "a string")
This is a string
Numbers
println(1 + 1)
2
Ranges
println((1 to 5))
Range 1 to 5
Values
Values are immutable
val x = 1 + 1
x: Int = 2
Variables
Variables are similar to values, but can be re-assigned
var y = 1 + 1
y = y + 1
y: Int = 3
Blocks
Expressions can be combined together in blocks surrounded by curly braces {}
println({
val z = 2
z + 2
})
4
Functions
val addOne = (x: Int) => x + 1
println(addOne(5))
6
addOne: Int => Int = ammonite.$sess.cmd31$$$Lambda$1460/0x00000008011a87d8@39ff4421
Compose
val f = (s: String) => "(" + s + ")"
val g = (s: String) => "(" + s + ")"
f: String => String = ammonite.$sess.cmd80$$$Lambda$1704/0x00000008011e6ef0@55ba1297
g: String => String = ammonite.$sess.cmd80$$$Lambda$1705/0x00000008011e72a0@be4982d
println(f("in parentheses"))
(in parentheses)
val fComposeG = f compose g
fComposeG: String => String = scala.Function1$$Lambda$1709/0x00000008011e1c20@23afde4a
println(fComposeG("in double parentheses"))
((in double parentheses))
Methods
def add(x: Int, y: Int): Int = x + y
println(add(1, 2))
3
defined function add
Classes
class Greeter(prefix: String, suffix: String) {
def greet(name: String): Unit =
println(prefix + name + suffix)
}
defined class Greeter
val greeter = new Greeter("Hello, ", "!")
greeter.greet("Damien")
Hello, Damien!
greeter: Greeter = ammonite.$sess.cmd34$Greeter@7585531b
Case Classes
Immutable and compared by value (not reference like classes
)
case class Point(x: Int, y: Int)
defined class Point
val point = Point(1, 2)
val anotherPoint = Point (1, 2)
println(point == anotherPoint)
true
point: Point = Point(x = 1, y = 2)
anotherPoint: Point = Point(x = 1, y = 2)
Objects
Singletons of their own classes
object IdFactory {
private var counter = 0
def create(): Int = {
counter += 1
counter
}
}
defined object IdFactory
val newId: Int = IdFactory.create()
println(newId)
val newerId: Int = IdFactory.create()
println(newerId)
1
2
newId: Int = 1
newerId: Int = 2
Traits
trait Greeter {
def greet(name: String): Unit =
println("Hello, " + name + "!")
}
defined trait Greeter
class DefaultGreeter extends Greeter
class CustomizableGreeter(prefix: String, postfix: String) extends Greeter {
override def greet(name: String): Unit = {
println(prefix + name + postfix)
}
}
val greeter = new DefaultGreeter()
greeter.greet("Damien")
val customGreeter = new CustomizableGreeter("How are you, ", "?")
customGreeter.greet("Damien")
Hello, Damien!
How are you, Damien?
defined class DefaultGreeter
defined class CustomizableGreeter
greeter: DefaultGreeter = ammonite.$sess.cmd46$DefaultGreeter@61f18402
customGreeter: CustomizableGreeter = ammonite.$sess.cmd46$CustomizableGreeter@63b187f
Data Structures
Collections
Tuples
Fixed number of elements. Heterogeneous (can hold multiple types). One-indexed.
val t = (1, "hello", Console)
t: (Int, String, Console.type) = (1, "hello", scala.Console$@fc807c1)
Above is syntactic sugar for:
val t = new Tuple3(1, "hello", Console)
t: (Int, String, Console.type) = (1, "hello", scala.Console$@fc807c1)
Accessing an element by index
println(t._2)
hello
Short form for tuples with only two elements
val short_t = 1 -> 2
short_t: (Int, Int) = (1, 2)
Swap elements for tuples with only two elements
println(short_t.swap)
(2,1)
Arrays
Mutable
val a = Array(1, 2, 3)
a: Array[Int] = Array(1, 2, 3)
Lists
Immutable
val l = List('a', 'b', 'c')
l: List[Char] = List('a', 'b', 'c')
Access by index
println(l(0))
a
Length
println(l.length)
3
Reverse
println(l.reverse)
List(c, b, a)
Map
println(List(1, 2, 3).map(_ * 2))
List(2, 4, 6)
Filter
println(List(5, 6, 7, 8, 9, 10).filter(_ % 2 == 0))
List(6, 8, 10)
Reduce Left
println(List(1, 2, 3).reduceLeft(_ + _))
6
Range to List
println((1 to 5).toList)
List(1, 2, 3, 4, 5)
Prepend
println(0 :: List(1, 2, 3))
List(0, 1, 2, 3)
Sets
Iterables that can't have duplicate elements
val provinces = Set("Quebec", "Ontario", "Manitoba")
provinces: Set[String] = Set("Quebec", "Ontario", "Manitoba")
val otherProvinces = Set("Alberta", "Manitoba", "British Columbia")
otherProvinces: Set[String] = Set("Alberta", "Manitoba", "British Columbia")
Intersect
println(provinces & otherProvinces)
Set(Manitoba)
Union
println(provinces | otherProvinces)
HashSet(Quebec, Manitoba, Ontario, Alberta, British Columbia)
Subset of
println(otherProvinces subsetOf provinces)
false
println(Set(1, 2) subsetOf Set(1, 2, 3, 4, 5))
true
Diff
println(otherProvinces diff provinces)
Set(Alberta, British Columbia)
Maps
val countries = Map("FR" -> "France", "CA" -> "Canada", "US" -> "United States")
countries: Map[String, String] = Map("FR" -> "France", "CA" -> "Canada", "US" -> "United States")
Access by key
val fr = countries("FR")
fr: String = "France"
Add key/value
val moreCountries = countries + ("DE" -> "Germany")
moreCountries: Map[String, String] = Map("FR" -> "France", "CA" -> "Canada", "US" -> "United States", "DE" -> "Germany")
Keys
val keys = countries.keys
keys: Iterable[String] = Set("FR", "CA", "US")
Values
val values = countries.values
values: Iterable[String] = Iterable("France", "Canada", "United States")
Remove element by key
val lessCountries = countries - "US"
lessCountries: Map[String, String] = Map("FR" -> "France", "CA" -> "Canada")
Scala.js
https://www.scala-js.org/ Scala compiled to JavaScript
Frameworks
Slinky
Write React apps in Scala just like you would in ES6
Laminar
Native Scala.js library for building user interfaces
scalajs-react
https://github.com/japgolly/scalajs-react
Facebook's React on Scala.js
Resources
- https://docs.scala-lang.org/tour/basics.html
- https://docs.scala-lang.org/scala3/new-in-scala3.html
- https://docs.scala-lang.org/cheatsheets/
Metals (Scala Language Server)
- https://scalameta.org/metals/docs/editors/emacs/
- https://ag91.github.io/blog/2020/10/16/my-emacs-setup-for-scala-development/
Functional Programming
Scalaz
Cats
- https://github.com/typelevel/cats
- https://underscore.io/books/scala-with-cats/
- https://www.scalawithcats.com/
Zio
https://zio.dev/ Type-safe, composable asynchronous and concurrent programming for Scala
"The red book"
https://www.manning.com/books/functional-programming-in-scala