diff --git a/_overviews/scala3-book/domain-modeling-tools.md b/_overviews/scala3-book/domain-modeling-tools.md index 29d4c9eb69..bd9e955ba5 100644 --- a/_overviews/scala3-book/domain-modeling-tools.md +++ b/_overviews/scala3-book/domain-modeling-tools.md @@ -7,7 +7,6 @@ previous-page: domain-modeling-intro next-page: domain-modeling-oop --- - Scala 3 provides many different constructs so we can model the world around us: - Classes @@ -411,7 +410,12 @@ For more details, see the remainder of these modeling lessons. ## Abstract classes {% comment %} -TODO: I have some notes on when to use abstract classes, and can update this section. +LATER: If anyone wants to update this section, our comments about abstract classes and traits are on Slack. The biggest points seem to be: +- The `super` of a trait is dynamic +- At the use site, people can mix in traits but not classes +- It remains easier to extend a class than a trait from Java, if the trait has at least a field +- Similarly, in Scala.js, a class can be imported from or exported to JavaScript. A trait cannot +- There are also some point that unrelated classes can’t be mixed together, and this can be a modeling advantage {% endcomment %} When you want to write a class, but you know it will have abstract members, you can either create a trait or an abstract class. diff --git a/_overviews/scala3-book/fp-immutable-values.md b/_overviews/scala3-book/fp-immutable-values.md index c855b35ea4..c5a4cc3eb3 100644 --- a/_overviews/scala3-book/fp-immutable-values.md +++ b/_overviews/scala3-book/fp-immutable-values.md @@ -19,10 +19,6 @@ Using only immutable variables raises an interesting question: If everything is When it comes to using collections, one answer is that you don’t mutate an existing collection; instead, you apply a function to an existing collection to create a new collection. This is where higher-order functions like `map` and `filter` come in. -{% comment %} -TODO: need a better example -{% endcomment %} - For example, imagine that you have a list of names---a `List[String]`---that are all in lowercase, and you want to find all the names that begin with the letter `"j"`, and then you want to capitalize those names. In FP you write this code: diff --git a/_overviews/scala3-book/fp-pure-functions.md b/_overviews/scala3-book/fp-pure-functions.md index f8cbf2ea16..e9aff86437 100644 --- a/_overviews/scala3-book/fp-pure-functions.md +++ b/_overviews/scala3-book/fp-pure-functions.md @@ -8,15 +8,14 @@ next-page: fp-functions-are-values --- -{% comment %} -TODO: Use someone else’s definition? -{% endcomment %} - Another feature that Scala offers to help you write functional code is the ability to write pure functions. A _pure function_ can be defined like this: - A function `f` is pure if, given the same input `x`, it always returns the same output `f(x)` -- The function’s output depends *only* on its input variables and its internal algorithm +- The function’s output depends _only_ on its input variables and its implementation +- It only computes the output and does not modify the world around it + +This implies: - It doesn’t modify its input parameters - It doesn’t mutate any hidden state - It doesn’t have any “back doors”: It doesn’t read data from the outside world (including the console, web services, databases, files, etc.), or write data to the outside world @@ -42,23 +41,23 @@ These `String` methods are also pure functions: Most methods on the Scala collections classes also work as pure functions, including `drop`, `filter`, `map`, and many more. -> In Scala, *functions* and *methods* are almost completely interchangeable, so even though we use the common industry term “pure function,” this term can be used to describe both functions and methods. +> In Scala, _functions_ and _methods_ are almost completely interchangeable, so even though we use the common industry term “pure function,” this term can be used to describe both functions and methods. > If you’re interested in how methods can be used like functions, see the [Eta Expansion][eta] discussion. ## Examples of impure functions -Conversely, the following functions are *impure* because they violate the definition. +Conversely, the following functions are _impure_ because they violate the definition. The `foreach` method on collections classes is impure because it’s only used for its side effects, such as printing to STDOUT. > A great hint that `foreach` is impure is that it’s method signature declares that it returns the type `Unit`. > Because it doesn’t return anything, logically the only reason you ever call it is to achieve some side effect. -> Similarly, *any* method that returns `Unit` is going to be an impure function. +> Similarly, _any_ method that returns `Unit` is going to be an impure function. Date and time related methods like `getDayOfWeek`, `getHour`, and `getMinute` are all impure because their output depends on something other than their input parameters. -Their results rely on some form of hidden I/O; *hidden inputs,* in these examples. +Their results rely on some form of hidden I/O; _hidden inputs,_ in these examples. Additionally, methods that interact with the console, files, databases, web services, sensors, etc., are all impure. @@ -111,8 +110,8 @@ If you understand that code, you’ll see that it meets the pure function defini The first key point of this section is the definition of a pure function: -> A *pure function* is a function that depends only on its declared inputs and its internal algorithm to produce its output. -> It does not read any other values from “the outside world”---the world outside of the function’s scope---and it doesn’t modify any values in the outside world. +> A _pure function_ is a function that depends only on its declared inputs and its implementation to produce its output. +> It only computes its output and does not depend on or modify the outside world. A second key point is that every real-world application interacts with the outside world. Therefore, a simplified way to think about functional programs is that they consist of a core of pure functions that are wrapped with other functions that interact with the outside world. diff --git a/_overviews/scala3-book/fp-what-is-fp.md b/_overviews/scala3-book/fp-what-is-fp.md index 9899dfb996..0b380447c8 100644 --- a/_overviews/scala3-book/fp-what-is-fp.md +++ b/_overviews/scala3-book/fp-what-is-fp.md @@ -9,12 +9,7 @@ next-page: fp-immutable-values -[Wikipedia defines *functional programming*](https://en.wikipedia.org/wiki/Functional_programming) like this: - - -{% comment %} -TODO: Update the CSS so this extra paragraph isn’t needed. -{% endcomment %} +[Wikipedia defines _functional programming_](https://en.wikipedia.org/wiki/Functional_programming) like this:

Functional programming is a programming paradigm where programs are constructed by applying and composing functions. @@ -26,8 +21,8 @@ This allows programs to be written in a declarative and composable style, where It can also be helpful to know that experienced functional programmers have a strong desire to see their code as math, that combining pure functions together is like combining a series of algebraic equations. -When you write functional code you feel like a mathematician, and once you understand the paradigm, you want to write pure functions that always return *values*---not exceptions or null values---so you can combine (compose) them together to create solutions. -The feeling that you’re writing math-like equations (expressions) is the driving desire that leads you to use *only* pure functions and immutable values, because that’s what you use in algebra and other forms of math. +When you write functional code you feel like a mathematician, and once you understand the paradigm, you want to write pure functions that always return _values_---not exceptions or null values---so you can combine (compose) them together to create solutions. +The feeling that you’re writing math-like equations (expressions) is the driving desire that leads you to use _only_ pure functions and immutable values, because that’s what you use in algebra and other forms of math. Functional programming is a large topic, and there’s no simple way to condense the entire topic into one chapter, but hopefully the following sections will provide an overview of the main topics, and show some of the tools Scala provides for writing functional code. diff --git a/_overviews/scala3-book/fun-eta-expansion.md b/_overviews/scala3-book/fun-eta-expansion.md index b801631a16..d48e6c059b 100644 --- a/_overviews/scala3-book/fun-eta-expansion.md +++ b/_overviews/scala3-book/fun-eta-expansion.md @@ -8,25 +8,25 @@ next-page: fun-hofs --- -When you look at the Scaladoc for the `map` method on Scala collections classes, you see that it’s defined to accept a *function*: +When you look at the Scaladoc for the `map` method on Scala collections classes, you see that it’s defined to accept a _function_: ```scala def map[B](f: (A) => B): List[B] ----------- ``` -Indeed, the Scaladoc clearly states, “`f` is the *function* to apply to each element.” -But despite that, somehow you can pass a *method* into `map`, and it still works: +Indeed, the Scaladoc clearly states, “`f` is the _function_ to apply to each element.” +But despite that, somehow you can pass a _method_ into `map`, and it still works: ```scala def times10(i: Int) = i * 10 // a method List(1, 2, 3).map(times10) // List(10,20,30) ``` -Have you ever wondered how this works---how you can pass a *method* into `map`, which expects a *function*? +Have you ever wondered how this works---how you can pass a _method_ into `map`, which expects a _function_? -The technology behind this is known as *Eta Expansion*. -It converts an expression of *method type* to an equivalent expression of *function type*, and it does so seamlessly and quietly. +The technology behind this is known as _Eta Expansion_. +It converts an expression of _method type_ to an equivalent expression of _function type_, and it does so seamlessly and quietly. @@ -37,14 +37,9 @@ NOTE: I got the following “method” definition from this page (https://dotty. I’ve made a few changes to that description that I hope are more accurate and up to date. {% endcomment %} +Historically, _methods_ have been a part of the definition of a class, although in Scala 3 you can now have methods outside of classes, such as [Toplevel definitions][toplevel] and [extension methods][extension]. -{% comment %} -TODO: link to Toplevel definitions -{% endcomment %} - -Historically, *methods* have been a part of the definition of a class, although in Scala 3 you can now have methods outside of classes, such as Toplevel definitions and [extension methods][extension]. - -Unlike methods, *functions* are complete objects themselves, making them first-class entities. +Unlike methods, _functions_ are complete objects themselves, making them first-class entities. Their syntax is also different. This example shows how to define a method and a function that perform the same task, determining if the given integer is even: @@ -89,3 +84,4 @@ For more details on how this works, see the [Eta Expansion page][eta_expansion] [eta_expansion]: {{ site.scala3ref }}/changed-features/eta-expansion.html [extension]: {% link _overviews/scala3-book/ca-extension-methods.md %} +[toplevel]: {% link _overviews/scala3-book/taste-toplevel-definitions.md %} diff --git a/_overviews/scala3-book/scala-features.md b/_overviews/scala3-book/scala-features.md index 1df980d863..048d7e4519 100644 --- a/_overviews/scala3-book/scala-features.md +++ b/_overviews/scala3-book/scala-features.md @@ -124,7 +124,7 @@ val z = nums.filter(_ > 100) .map(_ * 2) ``` -Because Scala is considered to be a [strong, statically-typed language](https://heather.miller.am/blog/types-in-scala.html), you get all the benefits of static types: +As Heather Miller states, Scala is considered to be a [strong, statically-typed language](https://heather.miller.am/blog/types-in-scala.html), and you get all the benefits of static types: - Correctness: you catch most errors at compile-time - Great IDE support @@ -147,12 +147,6 @@ In that list: - Reliable code completion {% endcomment %} -{% comment %} -In this section or the next section: -- TODO: Add a note about the benefits of the DOT calculus -- TODO: Also add a note about TASTy? -{% endcomment %} - ### Expressive type system diff --git a/_overviews/scala3-book/scala-for-java-devs.md b/_overviews/scala3-book/scala-for-java-devs.md index 4ecf11a238..5ed39eb9ee 100644 --- a/_overviews/scala3-book/scala-for-java-devs.md +++ b/_overviews/scala3-book/scala-for-java-devs.md @@ -53,7 +53,10 @@ Also at a high level, the differences between Java and Scala are: - The [Scala Native](http://www.scala-native.org) project adds low-level constructs to let you write “systems” level code, and also compiles to native executables {% comment %} +These are several notes that came up early in the writing process, and I (Alvin) can’t really address them: TODO: Need a good, simple way to state that Scala has a sound type system +TODO: Points to make about Scala’s consistency? +TODO: Add a point about how the type system lets you express details as desired {% endcomment %} @@ -61,11 +64,6 @@ TODO: Need a good, simple way to state that Scala has a sound type system Finally, these are some of the differences you’ll see every day when writing code: -{% comment %} -TODO: points to make about Scala’s consistency? -TODO: add a point about how the type system lets you express details as desired -{% endcomment %} - - Scala’s syntax is extremely consistent - Variables and parameters are defined as `val` (immutable, like `final` in Java) or `var` (mutable) - *Type inference* makes your code feel dynamically typed, and helps to keep your code brief