Course Overview
This is a great course that familiarises developers with The Scala Programming language (Version 3.x, previously known as Dotty).
This fresh and comprehensive course equips developers with all the tools necessary to function as a successful and productive team member on all Scala 3 projects.
Course Prerequisites
Students should be familiar with another programming language such as Java, C#, C++, Rust, Javascript/Typescript, Python etc. Having knowledge of a typed language will be beneficial.
Outline
This is not an upgrade course to Scala 3, but instead a course for newcomers to Scala who want to dive immediately into the latest version. We have an upgrade course available as well: SCALA-UPGRADE-3. If you are looking for a Scala 2 course, we recommended SCALA-CORE2
We are aware that many teams and developers follow Scala courses using recorded session or perhaps live webinar type of training and even more so during pandemic and economic crises.
These kinds of courses are great for learning products and easier concepts. However, they don't lend themselves to understanding new and often difficult concepts as they don't allow the ability to ask your own questions. Everybody is unique in their ability to comprehend and understand new concepts. And everyone needs a personalized approach. In addition, hearing questions/concerns from other students can help you tremendously. There might be ideas and answers you haven't thought about. Even without you asking a question, an instructor on a live instructor-led course will see from non-verbal communication that a particular concept needs to be rephrased, needs a different diagram or example or needs to be revisited later.
EDC4IT has been working with Scala since the early 2000s, and has taught many teams.
We worked together with different teams on their projects.
This course covers:
- Introduction to Scala, tools and the language
- Using OO concepts
- Functional Programming with Scala
- Higher kinded Types
- Collections
- using and building ADTs (using enums and traits)
- Bundled Monads and Functors
- Error Handling
- Concurrency and Futures
- Type bounds and variance
- Implicit conversions and extension methods
- Type classes
- Opaque type aliases
This course is unique in:
- being not just example driven, but bringing a deeper understanding of the Scala language
- explaining concepts that are often challenging in a clear manner (illustrating many approaches to different issues with the help of useful diagrams)
- focusing on preparation for real-world projects (discussing real problems, caveats, best practices)
Introduction
- Introduction to the Scala language
- Understand key features of the language
- Scala on the JVM
- Scala versions and Java Requirements
- Using the Scala CLI
- List popular scala tools (sbt, ammonite, scalafmt, …)
- Introduction to the Scala REPL
- Using the scala CLI
- Introduce sbt to set up a project
Language Basics
- Explore lexical syntax
- Explore scala's literal values
- Understand basic declarations and definitions (
var
,val
anddef
) - Declaring and using variables
- Understand basic types (Integers, floating point, …)
- Types with fixed cardinality (
Nothing
,Null
,Unit
andBoolean
) - Enable and use Explicit nulls
- Working with Strings
- Program using significant whitespace (aka "optional braces")
- Defining and Using union types
Method and functions
- Explore the methods syntax
- Understand aspects such as multiple parameter clauses, default values, repeated parameters
- Appreciate type inference
- Understand function application ("calling" functions)
- Explore more expressions (e.g,
if
-expressions)
Recursion
- Use recursion to problems
- Learn how to recognise recursive solutions
- Recursion and the stack
- Explain tail-call, its elimination and in particular tail recursive
Classes and Objects
- Understand scala's hierarchy (
Any
,AnyVal
) - Understand the bottom types
Nothing
andNull
- Use scala's explicit nulls
- Understand (multiversal) equality
- Understand the difference between objects, classes and traits
- Understand the difference between instances and objects
Classes
- Be able to define classes
- Appreciate the access modifiers and further qualification
- Adding fields and properties
- Recap methods declarations
- infix notation (and symbolic methods)
- Define constructors (primary and auxiliary)
- Method overloading
- Define type aliases
- Understand class inheritance (nominal sub-typing)
- Be able to apply the Liskov Substitution Principle
- Allow concrete classes to be extended using open classes
- Prevent ad-hoc extensions using final
- Concepts such as abstract members and overriding (methods and vals)
- Discuss composition over inheritance
- Understand the benefits of the Law of Demeter
- Introduce export clauses
Objects
- Define Objects in Scala
- Understand the concepts of Companion Objects and their typical use
- Understand the apply and unapply methods
Case classes
- Appreciate case classes
- Discuss immutability
- "updating" objects and immutability
- Understand use-cases for case classes
Value Classes
- Define value classes
- Why you should not use simple types (String, Int etc.)
- Understand caveats with value classes
Packages
- Organise classes/objects in packages
- Discuss different styles of importing packages and classes/objects
- Appreciate the top-level definitions
- renaming imports
- Organising your code
Creating Applications
- List the two ways of creating applications
- Using @main to define an application
- Use the legacy main methods
- Dealing with application arguments*
Traits
- Introduce traits
- Discuss the principle of mix-ins
- Different ways of mixing in traits
- Use traits to enrich interfaces of other types
- Discuss sealed types
- Solve problems when mixing in traits with params
- Appreciate transient traits
- Understand the linearisation process
- Solve conflicts
- Understand the stackable trait pattern
- Discuss abstract classes and traits
- Defining and using intersection types
Type Constructors (Introduction)
- Understand the different kind of types
- What are higher-kinded types
- Appreciate type constructors
- Mixin traits with type constructors (e.g.,
Ordered
)
Functions
Theory
- Understand domain, codomain and image of a function
- Discuss different types of functions: injective, Surjective, Bijective and Partial
- Understand the arity of a function
- Properties of a function
- Functions as values
Functions in Scala Introduction
- Defining functions
- Difference between functions and methods
- Use methods on functions (
compose
, ...) - The function literal syntax
- The function type literal syntax
- Use Lambda expressions
- Using methods as functions (automatic η-expansion)
- Functions as objects (e.g.,
Function0
,Function1
, …) - Function composition
- Early return using boundary and break
High-order function
- Understand the concept of Higher order functions
- Accepting functions and parameters
- returning functions from functions
- Understand clojures
- Discuss various use cases
- Using placeholder syntax (understand the expansion)
- Understand by name parameters
Currying
- Appreciate currying (methods and functions)
- Discuss use-cases
- Use partial function application
- Using optional partial application
ADTs
Introduction
- Rethink the concepts of Types
- Types (e.g., case classes) and their cardinality
- Introduction to Algebraic Data Types (ADTs)
- Understand the concept of product types
- Introduce Pairs and their projections
- Introduce coproducts (aka sum types)
- Defining coproducts
- Algebra with product types
- A categorical view of ADTs
- Parametrised ADTs
- Mention and discuss Generalized algebraic data types (GADT)
Enums
- Introduce enums
- Using enums as simple named values
- Using enums for sum/coproduct ADTs (vs. traits)
Pattern Matching
- Introduce the power of pattern matching
- Understand various patterns
- Understand the role of case classes
- Build extractors
- Understand sealed traits
- Pattern matching on ADTs
- Understand pattern matching in value definitions
- Introduce the concept of Partial Functions
Optional Values
- How to abstract the absents of a value
- Problem with using bottom values such as null
- Using the Option ADT
- Using
Option
in your programs - How to use option with side effects
- Using option as a Functor (mapping with
map
) - Using option as a Monad (sequentially compose using
flatmap
) - Introduce for-comprehensions
- Adding definitions and guards
Collections
Introduction
- Understand the type hierarchy (
IterableOnce
,Iterable
etc.) - Understand the collection's architecture
- Understand the role of ops types (e.g.,
IterableOnceOps
) - Mutable and immutable collections
- Creating collection instances
- Collections and equality
- Ordering collections
- Integrating with JVM collections
- Using for-comprehensions on collections
IterableOnce and Iterable
- Using collections as functors (mapping using
map
) - Getting elements from the collection
- Finding and Filtering elements
- Using partial functions to collect elements
- Adding elements to a collection
- Splitting and combining collections
Seq
- Working with indexed collections
- Searching for elements
- Adding to the head or the tail
- Replacing elements
- Sorting indexed collections
- Comparing and using set-operations on collections
- Discuss implementation and each of their benefits
- When to use Vector, List and other implementations
- Discuss performance consideration (operations and big-O)
List as a GADT
- Understand concepts such as head, tail, Cons, init, …
- Using Cons to construct a list
- Pattern matching Lists
Sets and Maps
- Working with Sets
- Performing set operations (intersection, union, …)
- Adding and removing set elements
- List various implementations and their benefits (
TreeSet
,HashSet
, …) - Discuss different algorithms and their performance
- Using Map
- getting, updating and iterating over maps
- Map implementations (
TreeMap
,HashMap
, …) and their perforce
Folding and Reducing
- Using reduction
- Using associative folds using monoidal reduction
- Using linear fold using an initial value
- Understand the difference between reduce and fold
- Understand the role of the natural element in folds
- The difference between fold, foldRight and foldLeft
- When to use which
- Using scan
Core effects
Errors
- Understand Errors and exceptions on the JVM
- Using JVM exception in Scala
- Using the Try ADT instead
- Working with the Try ADT as a functor (
map
) - composing using
flatmap
- Translating to other ADTs
- Discuss the various ways of recovery
- Using the Either ADT
- Using
Either
as an alternative for errors - Building your own error ADT
- Translating errors.
Concurrency and Futures
- Understand the difference between concurrency and Parallelism
- Understand JVM Threads and its pools
- Using Futures for concurrency
- Understand the role of the Execution Context
- Lifting values into a
Future
- Using
Future
as a functor/monad - Working with side effects after completion
- Handling and recovering from failures
- Combing futures (fold, zip, …)
- Appreciate Traverse and Sequence
Advanced Types
Higher-kinded types
- Recap Higher kinded types
- Introduce polymorphic methods
- Define polymorphic function types
- Type bounds (Upper, Lower and Context)
- Introduce the concept of variance
- Learn when to use covariance or contravariance
- When to keep types invariant
- Understand covariance or contravariance positions
- When to use Lower Bounds
Abstract Types
- Introduce Abstract Type Definitions
- Using Abstract Type Definitions to solve different problems
- Using Path Dependent types
- Refinement types and Programmatic Structural types
- Appreciate scala.Selectable
- Caveats of using Structural types
- Using Self-Types
- Using self-types for dependency injection (DI)
- Discuss DI alternatives
Context (Implicits)
- Understand the concept of the implicit context
- Understand the rules for brining in implicits into scope
- Appreciate prioritizing of implicits
- Define low priority implicits
- Best practices for implicits
- Define and use implicit conversions to convert between types
- Enrich types using extension methods
- Using givens/using to define contextual parameters
Type classes
- Understand the limitations of subtype polymorphism
- Introduce the concept of ad-hoc polymorphism Type classes
- What makes up a type class in Scala?
- Define a type class
- Provide instances using givens
- Add extension methods
- Summoning implicates in the current context
- Using Context Bounds
- Discuss use-cases and implement common type-classes (
Show
,Functor
, …) - Understand and use the concept of type-class derivation
- Provide and use the derives clause
Opaque Type aliases
- Recap value types
- Understand the concepts of Opaque Type aliases
- Defining opaque types
- Expose ways to lift values to their internal type
- Add methods to your new type