## 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`

and`def`

) - Declaring and using
**variables** - Understand
**basic types**(Integers, floating point, …) - Types with fixed cardinality (
`Nothing`

,`Null`

,`Unit`

and`Boolean`

) - 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`

and`Null`

- 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