Skip to content

Commit

Permalink
Updated EEP for behaviors with strict generators
Browse files Browse the repository at this point in the history
  • Loading branch information
lucioleKi authored and bjorng committed Nov 6, 2024
1 parent fbcb51a commit 2985b3e
Showing 1 changed file with 50 additions and 5 deletions.
55 changes: 50 additions & 5 deletions eeps/eep-0073.md
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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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

View workflow job for this annotation

GitHub Actions / markdownlint

Reference links and images should use a label that is defined

eeps/eep-0073.md:218:1 MD052/reference-links-images Reference links and images should use a label that is defined [Missing link or image reference definition: "4"] [Context: "[EEP-70][4]"] https://github.com/DavidAnson/markdownlint/blob/v0.35.0/doc/md052.md
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
-----------------

Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 2985b3e

Please sign in to comment.