Skip to content

Commit

Permalink
Switch to the suggested strict/relaxed naming convention
Browse files Browse the repository at this point in the history
  • Loading branch information
dszoboszlay committed Oct 12, 2024
1 parent da7d7ba commit 42d0498
Showing 1 changed file with 16 additions and 20 deletions.
36 changes: 16 additions & 20 deletions eeps/eep-0070.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,52 +5,53 @@
Erlang-Version: 28
Post-History:
****
EEP 70: Non-filtering generators
EEP 70: Strict and relaxed generators
----

Abstract
========

This EEP proposes the addition of a new, *non-skipping* variant of all
This EEP proposes the addition of a new, *strict* variant of all
existing generators (list, bit string and map). Currently existing
generators are *skipping*: they ignore terms in the right-hand side
expression that do not match the left-hand side pattern. Non-skipping
generators are *relaxed*: they ignore terms in the right-hand side
expression that do not match the left-hand side pattern. Strict
generators on the other hand shall fail with exception `badmatch`.

Rationale
=========

The motivation for non-skipping generators is that skipping generators
The motivation for strict generators is that relaxed generators
can hide the presence of unexpected elements in the input data of a
comprehension. For example consider the below snippet:

[{User, Email} || #{user := User, email := Email} <- all_users()]

This list comprehension would skip users that don't have an email
This list comprehension would filter out users that don't have an email
address. This may be an issue if we suspect potentially incorrect input
data, like in case `all_users/0` would read the users from a JSON file.
Therefore cautious code that would prefer crashing instead of silently
skipping incorrect input would have to use a more verbose map function:
filtering out incorrect input would have to use a more verbose map
function:

lists:map(fun(#{user := User, email := Email}) -> {User, Email} end,
all_users())

Unlike the generator, the anonymous function would crash on a user
without an email address. Non-skipping generators would allow similar
without an email address. Strict generators would allow similar
semantics in comprehensions too:

[{User, Email} || #{user := User, email := Email} <:- all_users()]

This generator would crash (with a `badmatch` error) if the pattern
wouldn't match an element of the list.

The proposed operators for non-skipping generators are `<:-` (for lists
The proposed operators for strict generators are `<:-` (for lists
and maps) and `<:=` (for bit strings) instead of `<-` and `<=`. This
syntax was chosen because `<:-` and `<:=` somewhat resemble the `=:=`
operator that tests whether two terms match, and at the same time keep
the operators short and easy to type. Having the two types of operators
differ by a single character, `:`, also makes the operators easy to
remember as "`:` means non-skipping."
remember as "`:` means strict."

Alternate Designs
=================
Expand Down Expand Up @@ -84,7 +85,7 @@ encountering non-matching input:
|| Usr <- all_users(),
#{user := User, email := Email} = Usr]

Most of these solutions are much more verbose than the non-skipping
Most of these solutions are much more verbose than the strict
generator syntax, undermining the compactness of comprehensions. But
there are more serious issues too:

Expand All @@ -97,8 +98,8 @@ there are more serious issues too:
* The intent of the code isn't clear in most of these solutions
(definitely not in 3, and arguably in 4 and 2).

* None of these techniques can solve the last non-matching bits of a
bit string problem.
* None of these techniques can solve the problem of final non-matching
bits of a bit string.

The issue with bit string generators is that unlike lists and maps, bit
strings don't have natural "elements" the generator could iterate over.
Expand All @@ -109,8 +110,8 @@ this example:

[X || <<X:16>> <- <<1,2,3>>]

The existing generator would skip these last non-matching bits, and this
behaviour cannot be changed due to backward compatibility reasons.
The existing generator would skip these final non-matching bits, and
this behaviour cannot be changed due to backward compatibility reasons.
It is only possible to guarantee that a bit string generator would fully
consume its input by introducing a new type of bit string generator or
some other new syntax that would alter the behaviour of the existing
Expand All @@ -128,11 +129,6 @@ There are no backward compatibility issues with the proposed new syntax,
since the `<:-` and `<:=` operators used to be invalid syntax in
previous versions of Erlang.

Furthermore, non-skipping generators can be added as an experimental
feature that has to be explicitly enabled:

-feature(non_skipping_generators,enable).

[PR #8625]: https://github.com/erlang/otp/pull/8625
"Reference implementation PR"

Expand Down

0 comments on commit 42d0498

Please sign in to comment.