
This is part three of a three part course, the first part covers converting to Scala from other programming languages and part two covers Scala language features that might be different from other languages or perhaps even unique. This part three finishes the tour of powerful language features with case classes and pattern matching, then moves on to the most important core library features, like collections, futures, and also covers building and working with Java.
Slides and exercises are attached to the next lecture.
Explore advanced Scala pattern matching, including guards, type narrowing, try, case classes and constructor patterns, and core libraries like options, collections, and tuples, plus custom extractors.
Explore Scala's match construct with constant matches, learn how it differs from Java switch, and see how case underscore handles all other cases with a unit side effect.
Use pattern match as an expression to map a string to a result, returning different strings for inputs like fish and chips, bacon and eggs, or tea and scones.
Discover pattern matching with variable loads that bind a value to an identifier, enabling string interpolation and opposites like hot to cold and full to empty.
Explain how Scala pattern matching distinguishes constants from variables using capitalization, with max limit as a constant and min limit as a variable, via def is a limit.
Explore how Scala pattern matching treats constants vs variables, using capitalization and backticks to avoid shadowing, and review compiler warnings about unreachable patterns.
Place the predicate on the left side of the arrow when using a guard to avoid warnings and unreachable code, since right-side guards can yield any and unit in return.
Explore option types as a safe alternative to nulls and practice pattern matching on options with guards, case clauses, and none handling, including idiomatic getOrElse usage.
Explore how Scala tuples use pattern matching to extract int, boolean, and string, with first-one precedence, conditional loads, and a catch-all case that matches any remainder.
Explore the capital T Try as a result type with success or failure, using pattern matching to handle try of int versus throwable and recover with get or else.
Explore scala case classes, enabling pattern matching on nested domain objects, optional fields, and convenient factory methods with automatic toString representations.
Case classes automatically generate equals and hashCode, with pattern matching limitations preventing inheritance of other case classes. They expose constructor parameters as public parametric fields, enabling direct access like address.city.
Explore compound pattern matches in Scala by using case classes to match constants, capture variables, and extract address components to retrieve a postcode.
Learn typed pattern matches in scala to narrow types safely, replacing runtime checks and casts with type patterns like case i of int, enabling guards and method calls.
Explore type erasure on the JVM, how runtime types differ from compiler types, and how to pattern match maps by using underscores and nested matches to avoid class cast exceptions.
Discover how vals enable pattern matching in Scala, using tuples and case class extractors to pull out fields like name, phone, and post code, and understand match errors.
Explore how partial functions become pattern matches in Scala, using curly brace cases to define either partial or complete functions, and replace map calls with direct pattern matching.
Enforce exhaustiveness with sealed class hierarchies in Scala to ensure pattern matching covers all algebraic data types, and receive compile-time warnings on missing cases to avoid runtime errors.
Explore how Scala case classes generate an unapply method in the companion object to support pattern matching, returning an option of the first name, last name, and age.
Learn to implement custom extractors in scala using an unapply method, returning options, to parse coordinate strings into latitude and longitude with pattern matching.
Learn to implement custom seq extractors in Scala by using unapply seek to extract any number of doubles from a comma-separated string, enabling sequence pattern matching.
Build the IntelliJ project, load modules 12 to 16, and fix the module 12 tests by uncommenting code to get everything working before exploring collections in module 13.
Explore Scala's simplest immutable data structure, the lists, and the start of the collections API, including cons and concat, while noting Vector's rising role.
Explore the immutable link list, learn how to initialize and convert to lists, and examine constant and linear time operations, higher order and predicate functions, folds, combiners, and sorting.
Explore how immutable Scala lists build with cons and nil as a recursive data structure, share memory during concatenation, and provide efficient head operations thanks to the tail pointer.
Explore immutable lists and covariant typing in scala, mastering efficient head operations, the nil bottom type, and the cons pattern within a sealed trait list design.
Learn how to initialize lists in Scala using the apply method and right‑associative cons, with nil, and use fill, tabulate, and range to generate sequences like 0 to 9.
Convert vectors, sets, maps, and strings to lists in Scala using toList, noting set order is not guaranteed and strings become lists of chars.
Explore covariance in lists: if A extends B, List[A] is a subtype of List[B], with nil and cons widening types to the least upper bound, enabling List[Any] compatibility.
Learn why last, init, and length incur linear time on immutable lists, and how head operations stay fast while non-head use and array mutability affect performance.
Explore position-dependent operations on lists, including apply and index access, take and drop, head option for safe access, and updating immutable lists to return new versions.
Explore higher order functions that take or return functions, with examples like map, flatMap, and flatten, and highlight that for each has a unit return and side effects.
Explore predicate based functions in Scala Applied, Part 3, and how predicates return booleans to drive list operations like filter, find, indexWhere, lastIndexWhere, filterNot, partition, takeWhile, and dropWhile.
Explore how fold left and fold right reduce lists with an identity value and a combiner, enabling sums, products, and string concatenation.
Explore fold alternatives in Scala applied, part 3, using built-in list operations like sum and product. Demonstrate make string with a separator, preamble, and postamble to intersperse words.
Sort lists in Scala using sort with, sort by, and sorted with implicit orderings for strings and integers, and supply a custom implicit person ordering to ensure stable, prioritized sorting.
Explore powerful collection methods in Scala, including transpose, flatten, and sum, and learn to group by to build a histogram from data.
Use collect, a partial function that combines map and filter to filter by type in a list and narrow results to apples, illustrated by a fruit example.
Explore Scala's grouped, sliding, combinations, and permutations on a 0–9 list, learn lazy iterators and conversion to lists, and discover map and corresponds utilities for paired collections.
Explore indices, zip and unzip in Scala to pair items with their indices, enable ordered parallel processing, and return separate lists via unzip for the first and second components.
Explore Scala's common collections and their performance trade-offs versus lists, and examine other collections to understand their performance characteristics.
Scala's rich collection hierarchy, including traversable, iterable, and the three broad categories: sequences, sets, and maps, and how 2.13 changes simplify the API.
Explore performance characteristics of immutable sequences in Scala, comparing list and vector. Learn when constant time, linear, and amortized operations apply, and why vector often outperforms for non-head access.
Compare immutable and mutable sets and maps, including hash sets and maps with constant time operations, and tree sets and maps with log N operations like min and max.
Explore linear seq versus indexed seq in Scala, comparing list and vector as immutable defaults for head-first traversal and random access, and note array trade-offs with mutability and thread safety.
Explore the consistent collections API across lists, vectors, and stacks, covering construction, empty methods, and equality for sequences, with notes on array comparisons and same elements fixes.
Convert collections to list, vector, array, set, or map with concise to-type methods, noting maps require a sequence of pairs. Expect 2.13 syntax shifts to to queue and builder usage.
Explore Scala sequences, including queue mechanics with amortized constant time, stacks and lists, arrays with primitives and random access, ranges as arithmetic progressions, and lazy streams—plus vector performance.
The mighty vector in scala uses a 32-ary immutable trie to deliver near constant performance with memory reuse, where updates create new blocks along the path and require few hops.
Demonstrates how a vector with arity 32 enables navigation in at most seven hops, updates by duplicating 32-word blocks, and shows vector outperforms list on the JVM.
Explore immutable sets, their unique elements, and non-ordered storage. Use set operations: intersect, diff, and union, plus the apply method as a predicate to count vowels.
Compare hash sets with tree sets and learn how tree sets maintain order via implicit ordering. See mutable sets support add, remove, and membership checks, with immediate side effects.
Explore maps as key-value associations, using arrow syntax to construct tuples, safe retrieval with get and getOrElse, and mapping over keys like a function.
Explore immutable collections in Scala, including list, stream, vector, stack, and queue ranges. Cover hash sets and maps, small-arity optimizations, tree variants, bit-set encoding, and avoid list.map.
Explore lazy collections and iterators in Scala, noting side effects and not referentially transparent. Avoid using length on an iterator, and rely on hasNext and next to prevent exhaustion.
A view is a lazy, functional collection based on an existing one without modifying it, recording mapped functions and applying them just in time, trading off sparse access against iteration.
Continue module 14 exercises, using provided implementations to compare your versions, and practice constructing a mutation or polymorphism map before advancing to sbt and Java libraries in module 15.
Explore building Scala projects with Scala and Java together, navigate edge cases, master SBT as the primary build tool, and discuss other options while constructing custom tasks.
Explore scala build tools and sbt basics, commands, and customization, then learn to mix java and scala with scala 2.12 and java eight support, and handle java collections and nulls.
Explore Gradle as a popular build tool with polyglot support. Learn how Gradle's Groovy domain-specific language, a Scala plugin, and zinc incremental compiler make including Scala in your builds easy.
Explore various build tool options, from pants and ant to sbt, noting the changing landscape and sbt as the de facto standard for Scala projects.
Explore sbt, the de facto scala build tool, with a scala-like DSL and optional full scala usage, delivering fast compile and test optimization with tilde mode for continuous monitoring.
Explains the conventional sbt project layout, with sources under source/main/scala, resources, and tests under test, mirrored for integration tests, plus Play's slight deviations and an IntelliJ example.
Master the build.sbt file basics, including a minimal build file, a Scala-like DSL with three key operators (:=, +=, ++=), optional blank lines, and embedding Scala code inside curly braces.
Explore a minimal sbt build, with project name, organization, licenses, and compiler options. Understand scala versions, cross compilation, percent vs percent percent dependencies, and plugin publishing to bintray.
Discover how sbt plugins extend build capabilities via a plugins.sbt file under the project directory, and configure resolvers and plugins such as the bin tree and git plugins.
learn how to create a custom sbt setting and task, define setting keys and boolean flags, and compose them to mark a project as awesome.
Define a custom task key check awesome that depends on the test compile task, forces compilation, and logs the project's awesome rating.
Learn how Scala uses Java libraries on the JVM, from persistence layers and web frameworks to numerical and scientific tools, with lightweight wrappers like GeoTools.
The Scala compiler runs first on mixed Scala and Java sources, generating stubs to type check Scala. The Java compiler uses the resulting class files to produce the final jar.
Learn how to call Java from Scala, import Java libraries, and use Java methods with Scala syntax, including infix calls, primitive boxing, and SAM conversions on the JVM.
Scala 2.12 with Java 8 enables lighter function literals that compile to method handles. Scala functions now act as Java function interfaces with single abstract methods and Java 8 streams.
Compare old and new Java function approaches in Scala and Java, from single abstract method to Java lambda for sorting arrays. Observe boilerplate reduction and comparator usage in Scala 2.12.
Wrap Java results that may be null in an option to convert them to Some or None, then safely map over the option to avoid null pointer exceptions.
Explore how to use Scala options instead of nulls and seamlessly interoperate with Java libraries by converting Some/None to a reference or null when calling Java methods.
Learn how to convert java.util collections to Scala collections using Java converters, map over Java lists, and obtain an immutable list with toList, while mindful of mutability.
Discover how Java primitives and Scala boxing differ, and why you must explicitly box Scala lists to Java lists to avoid type mismatches when passing integers.
Explore how Scala traits and Java interfaces share implementations, focusing on pure abstract Scala traits that act as Java interfaces for reliable Java calling into Scala.
Explore Scala and Java interoperability with empty trait based APIs, avoid risky function literals, convert between nulls and options, and use Scala Java converters and REPL to explore libraries.
Practice module 15 by calling a fake Java library in tests to explore booleans, nulls, and array lists of integers, gaining Scala–Java interop fluency; module 16 covers futures.
Explore asynchronous programming in Scala using futures built into the core libraries. Learn how these futures enable concurrent programming and leverage Scala's concurrent library support.
Explore futures and their states, learn how to compose them, and understand promises and their relationship. Adapt Java futures to Scala futures and uncover common patterns and practical alternatives.
Learn how futures work: they start and may be unresolved, completed with success, or completed with failure; using map or flatMap keeps the thread unblocked while returning a future result.
Learn how to compose futures in Scala for non-blocking asynchronous programming, using map, flatMap, and for expressions to chain results without blocking.
Explore how futures resolve in async evaluation, demonstrating the longest delay of one second, dereferencing results in the yield block, and verifying behavior in the Repl.
Learn to force a Scala future's result with await.result and a timeout, avoiding blocking except at the top level or in tests, and compare await.ready to await.result.
Explore non blocking future operations like map, flatMap, collect, and filter, and narrow a future of any to a specific type with success or failure. Use transform to handle outcomes.
Learn non-blocking future operations such as and then, oncomplete, and for each to perform side effects, handle success and failure, and ensure resources like files are closed.
Explore how futures handle unresolved, successful, and failed states, and learn three recovery patterns, fallback to, recover, and recover with, to transform failures into usable results.
Handle an unknown number of futures with Future.sequence, turning a list of futures into a single future of a list; use traverse to map and sequence in one step.
Explore future sequence operations like first completed, futures reverse, and foldleft over a future of sequence, noting non-cancelable futures, non-blocking processing, and the empty-sequence risk of reduce left.
Explore the Scala futures mechanism by creating a promise as the server-side channel for a result, then push a value or exception to complete the future non-blockingly.
Explore how a broken promise turns a promise of int into a failed future with an exception, illustrating how failures complete promises and futures in Scala.
Explore Java's completable futures from Java eight onward and convert them to Scala futures using the Scala compat Java eight future converters, enabling non-blocking interoperability.
Examine batching patterns for futures on the JVM to prevent memory bloat and external resource overload by executing limited batches and awaiting each batch before starting the next.
Explore batching with futures by grouping items into batch sizes, folding over each batch from a future of an empty vector, and concatenating results as each batch completes.
Explore retrying patterns for unreliable external services, using a simulated counter to model failures and eventual success, and implement a framework to retry until success.
Master naive retrying with futures and fallbackTo, and implement non-blocking, periodic backoff for finite retries without blocking threads.
Learn to implement non-blocking retries with backoff using a Java eight asynchronous timer, futures, and promises, sequencing durations to retry an operation until success or failure.
Learn a generic, reusable retrying back-off utility in Scala, with a failing method and duration DSLs like 10s and two minutes. See it used in patterns for retrying and batching.
Scala Applied, part 3 is the final part of this Scala programming language course. The course in its entirety is aimed at giving you a full, day-to-day working knowledge of Scala programming, including some of the most common core library APIs.
This part starts with a final language feature for Scala (continuing from the other language features covered in parts 1 and 2). Pattern matching, partial functions and case classes are examined, how they can be used together, and how partial functions can help you avoid certain runtime errors by validating input to a function before you call it.
Then we delve into the collections API in the core libraries (a very in-depth 2 module examination of the capabilities and performance tradeoffs of the various collection options), and finish up with a look at using Scala on Java projects, using Java libraries from Scala and how to harness build tools (particularly SBT) to build your project and even write custom settings and tasks. Following that we look at the Futures API in the core libraries.
This course is also a good lead-in to the Stairway to Scala Advanced 3 part course which concentrates on in-depth language features, higher level functional abstractions, common patterns and idioms, type theory and other more advanced Scala concepts that will be particularly helpful for anyone writing their own libraries and APIs in Scala.