-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Updated EEP for behaviors with strict generators
- Loading branch information
Showing
1 changed file
with
50 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
Author: Isabell Huang <isabell(at)erlang(dot)org> | ||
Status: Draft | ||
Status: Final/28.0 Implemented in OTP release 28 | ||
Type: Standards Track | ||
Created: 21-Sep-2024 | ||
Erlang-Version: OTP-28.0 | ||
|
@@ -73,7 +73,7 @@ list of tuples. Variable bindings and pattern matching within a zip generator | |
works as expected, as `Nm` is supposed to bind to the same value in `{Nm,P}` | ||
and `{Nm,S}`. If the binding fails, then one element from each of the 3 | ||
generators is skipped. (If a strict generator is used, then the comprehension | ||
fails with exception `badmatch`, as specified in EEP-70.) | ||
fails with an exception, as specified in [Error Behaviors](#error-behaviors).) | ||
|
||
In summary, zip generators remove the user's need to call the zip function | ||
within comprehensions and allows for any number of lists to be zipped at once. | ||
|
@@ -138,6 +138,23 @@ filtered out from the resulting list. | |
|
||
[{X, Y} || X <- [a, b, c] && <<Y>> <= <<2, 4, 6>>, Y =/= 2]. | ||
|
||
The skipping behavior of individual generators within a zip generator is always | ||
respected. When strict generators are present in a zip generator, during every | ||
round of evaluation, all strict generators will be evaluated even if another | ||
relaxed generator already causes the result to be skipped. | ||
|
||
For example, the following comprehension has a zip generator containing a | ||
strict generator and a relaxed generator. | ||
|
||
[{X, Y} || {a, X} <:- L1 && {b, Y} <- L2] | ||
|
||
It will `badarg` if pattern matching for `{a, X}` fails, for example, when | ||
`L1 = [{a, 1}, {bad, 2}, {a, 3}]`. It will simply skip 1 item from `L1` and | ||
1 item from `L2` if pattern matching for `{b, Y}` fails, for example, when | ||
`L2 = [{b, 1}, {bad, 2}, {b, 3}]`. The attempt of matching `{a, X}` will | ||
be made every round, regardless of generators ordering and whether other | ||
pattern matchings succeed. | ||
|
||
Comparing to using helper functions, there is one advantage of using a zip | ||
generator: The Erlang compiler does not generate any tuple when a zip | ||
generator is translated into core Erlang. The generated code reflects the | ||
|
@@ -170,7 +187,7 @@ all generators. | |
|
||
For example, this comprehension will crash at runtime. | ||
|
||
[{X,Y} || X <- [1,2,3] && Y <- [1,2,3,4]]. | ||
[{X,Y} || X <- [1,2,3] && Y <- [1,2,3,4]]. | ||
|
||
The resulting error tuple is `{bad_generators,{[],[4]}}`. This is because | ||
when the comprehension crashes, the first list in the zip generator has | ||
|
@@ -183,6 +200,35 @@ different length comparing to others. The proposed error message aims to | |
gives the most helpful information without imposing extra burden on the | ||
compiler or runtime. | ||
|
||
Failed Strict Generator in a Zip Generator | ||
----------------- | ||
|
||
When a zip generator crashes because at least one strict generators contained | ||
in it fails, the resulting error tuple is of the same format as when generators | ||
are of different lengths. Its first element is the atom `bad_generators`, and | ||
the second element is a tuple containing remaining data from all generators. | ||
|
||
For example, this comprehension will crash at runtime, because `bad` cannot | ||
match the pattern `{ok,A}`. | ||
|
||
[A + B || {ok,A} <:- [bad, {ok,1}] && B <- [2,3]]. | ||
|
||
The resulting error tuple is `{bad_generators,{[bad, {ok,1}],[2,3]}}`. Although | ||
strict generators alone fail with exception `badmatch`, as specified in | ||
[EEP-70][4], it is not plausible to use the same exception in zip generators, | ||
Check failure on line 218 in eeps/eep-0073.md GitHub Actions / markdownlintReference links and images should use a label that is defined
|
||
due to difficulty in distinguishing between `badmatch` and `bad_generators` | ||
errors. | ||
|
||
In the following example, the comprehension will crash at runtime, either for | ||
the failed strict generator, or for two generators of different lengths. | ||
|
||
[A + B || {ok,A} <:- [bad] && B <- []]. | ||
|
||
The emitted error message is `{bad_generators,{[bad],[]}}`. We do not | ||
distinguish between the two errors, and instead always output all remaining | ||
data in the generators. The user can examine the remaining data and see that | ||
the first generator fails matching, and the second generator is empty. | ||
|
||
Non-generator in a Zip Generator | ||
----------------- | ||
|
||
|
@@ -212,8 +258,7 @@ this addition. | |
Reference Implementation | ||
======================== | ||
|
||
[compiler: Add zip generators for comprehensions][1] contains the implementation | ||
for zip generators. | ||
[PR-8926][1] contains the implementation for zip generators. | ||
|
||
[1]: https://github.com/erlang/otp/pull/8926 | ||
[2]: https://downloads.haskell.org/~ghc/5.00/docs/set/parallel-list-comprehensions.html | ||
|