Change docs/errors from "optional" to "default value" record fields

I strongly believe that seeing the word "optional" is priming people wrong when it comes to this feature.
Especially given roc dose not have an `Optional/Option/Maybe` type, so users look for an alternative and find this.

This PR changes the name to "default value record fields".
It updates all docs and errors.
It does not update compiler internal naming.
That can be updated in a follow up PR if we want to, but I am also fine leaving it cause it is not exposed to users.
This commit is contained in:
Brendan Hansknecht 2024-04-03 08:47:26 -07:00
parent 185262510c
commit 482c084096
No known key found for this signature in database
GPG Key ID: 0EA784685083E75B
6 changed files with 38 additions and 41 deletions

View File

@ -8,7 +8,7 @@
//! `{ b: "" }` have different derived implementations. However, it does not need to distinguish
//! between e.g. required and optional record fields.
//! - `Decoding` is like encoding, but has some differences. For one, it *does* need to distinguish
//! between required and optional record fields.
//! between required and default value record fields.
//!
//! For these reasons the content keying is based on a strategy as well, which are the variants of
//! [`DeriveKey`].

View File

@ -11167,9 +11167,9 @@ In roc, functions are always written as a lambda, like{}
}
Note: I can't derive decoding for a record with an optional field,
which in this case is `.y`. Optional record fields are polymorphic over
records that may or may not contain them at compile time, but are not
a concept that extends to runtime!
which in this case is `.y`. Default value record fields are polymorphic
over records that may or may not contain them at compile time, but are
not a concept that extends to runtime!
Maybe you wanted to use a `Result`?
"
);

View File

@ -416,7 +416,7 @@ fn underivable_hint<'b>(
Some(alloc.note("").append(alloc.concat([
alloc.reflow("I can't derive decoding for a record with an optional field, which in this case is "),
alloc.record_field(field),
alloc.reflow(". Optional record fields are polymorphic over records that may or may not contain them at compile time, "),
alloc.reflow(". Default value record fields are polymorphic over records that may or may not contain them at compile time, "),
alloc.reflow("but are not a concept that extends to runtime!"),
alloc.hardline(),
alloc.reflow("Maybe you wanted to use a "),

View File

@ -323,8 +323,8 @@ Here's how that `table` function would be implemented in Roc:
table = \{ height, width, title ? "", description ? "" } ->
```
This is using _optional field destructuring_ to destructure a record while
also providing default values for any fields that might be missing.
This is using _default value field destructuring_ to destructure a record while
providing default values for any fields that might be missing.
Here's the type of `table`:
```elixir
@ -339,28 +339,24 @@ table :
table = \{ height, width, title ? "", description ? "" } ->
```
This says that `table` takes a record with two _required_ fields (`height` and
`width` and two _optional_ fields (`title` and `description`). It also says that
the `height` and `width` fields have the type `Pixels` (a type alias for some
numeric type), whereas the `title` and `description` fields have the type `Str`.
This means you can choose to omit `title`, `description`, or both, when calling
the function...but if you provide them, they must have the type `Str`.
This says that `table` takes a record with two fields that are _required_, `height` and
`width`, and two fields that may be _omitted_, `title` and `description`. It also says that
the `height` and `width` fields have the type `Pixels`, a type alias for some
numeric type, and the `title` and `description` fields have the type `Str`.
This means you can choose to omit the `title`, `description`, or both fields, when calling
the function... but if you provide them, they must have the type `Str`.
This is also the type that would have been inferred for `table` if no annotation
had been written. Roc's compiler can tell from the destructuring syntax
`title ? ""` that `title` is an optional field, and that it has the type `Str`.
These default values can reference other expressions in the record destructure; if you
wanted, you could write
`{ height, width, title ? "", description ? Str.concat "A table called " title }`.
`title ? ""` that `title` is a default value field, and that it has the type `Str`.
Destructuring is the only way to implement a record with optional fields.
(For example, if you write the expression `config.title` and `title` is an
optional field, you'll get a compile error.)
Destructuring is the only way to implement a record with default value fields. For example,
if you write the expression `config.title` and `title` is a default value field,
you'll get a compile error.
This means it's never possible to end up with an "optional value" that exists
outside a record field. Optionality is a concept that exists only in record
fields, and it's intended for the use case of config records like this. The
ergonomics of destructuring mean this wouldn't be a good fit for data modeling.
Default values is a concept that exists only in record fields, and it's intended for the use
case of config records like this. The ergonomics of destructuring mean this wouldn't be a good
fit for data modeling, consider using a custom tag union or the `Result` type instead.
## Pattern matching

View File

@ -123,7 +123,7 @@ instead of `List.first : List a -> Maybe a`.) This is not only more self-descrip
other operations that can fail; there's no need to have functions like `Result.toMaybe` or `Maybe.toResult`,
because in Roc, the convention is that operations that can fail always use `Result`.
Second, optional record fields can be handled using Roc's Optional Record Field language feature, so using a type like `Maybe` there would be less ergonomic.
Second, optional record fields can be handled using Roc's Default Value Record Field language feature, so using a type like `Maybe` there would be less ergonomic.
To describe something that's neither an optional field nor an operation that can fail, an explicit tag union can be
more descriptive than something like `Maybe`. For example, if a record type has an `artist` field, but the artist

View File

@ -458,9 +458,9 @@ The `fromScratch` and `fromOriginal` records are equal, although they're defined
Note that `&` can't introduce new fields to a record, or change the types of existing fields.
(Trying to do either of these will result in an error at build time!)
## [Optional Record Fields](#optional-record-fields) {#optional-record-fields}
## [Default Value Record Fields](#default-value-record-fields) {#default-value-record-fields}
Roc supports optional record fields using the `?` operator. This can be a useful pattern where you pass a function a record of configuration values, some of which you'd like to provide defaults for.
Roc supports default value record fields using the `?` operator. This can be a useful pattern where you pass a function a record of configuration values, some of which you'd like to provide defaults for.
In Roc you can write a function like:
@ -468,14 +468,14 @@ In Roc you can write a function like:
table = \{
height,
width,
title? "oak",
description? "a wooden table"
title ? "oak",
description ? "a wooden table"
}
->
```
This is using _optional field destructuring_ to destructure a record while
also providing default values for any fields that might be missing.
This is using _default value field destructuring_ to destructure a record while
providing default values for any fields that might be missing.
Here's the type of `table`:
@ -490,23 +490,24 @@ table :
-> Table
```
This says that `table` takes a record with two _required_ fields, `height` and
`width`, and two _optional_ fields, `title` and `description`. It also says that
This says that `table` takes a record with two fields that are _required_, `height` and
`width`, and two fields that may be _omitted_, `title` and `description`. It also says that
the `height` and `width` fields have the type `Pixels`, a type alias for some
numeric type, and the `title` and `description` fields have the type `Str`.
This means you can choose to omit the `title`, `description`, or both fields, when calling the function... but if you provide them, they must have the type `Str`.
This means you can choose to omit the `title`, `description`, or both fields, when calling
the function... but if you provide them, they must have the type `Str`.
This is also the type that would have been inferred for `table` if no annotation
had been written. Roc's compiler can tell from the destructuring syntax
`title ? ""` that `title` is an optional field, and that it has the type `Str`.
`title ? ""` that `title` is a default value field, and that it has the type `Str`.
Destructuring is the only way to implement a record with optional fields. For example, if you write the expression `config.title` and `title` is an
optional field, you'll get a compile error.
Destructuring is the only way to implement a record with default value fields. For example,
if you write the expression `config.title` and `title` is a default value field,
you'll get a compile error.
This means it's never possible to end up with an _optional value_ that exists
outside a record field. Optionality is a concept that exists only in record
fields, and it's intended for the use case of config records like this. The
ergonomics of destructuring mean this wouldn't be a good fit for data modeling, consider using a `Result` type instead.
Default values is a concept that exists only in record fields, and it's intended for the use
case of config records like this. The ergonomics of destructuring mean this wouldn't be a good
fit for data modeling, consider using a custom tag union or the `Result` type instead.
## [Tags &amp; Pattern Matching](#tags) {#tags}