You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: text/0000-gen-fn.md
+34-13Lines changed: 34 additions & 13 deletions
Original file line number
Diff line number
Diff line change
@@ -18,6 +18,12 @@ Furthermore, add `gen fn` to the language. `gen fn foo(arg: X) -> Y` desugars to
18
18
# Motivation
19
19
[motivation]: #motivation
20
20
21
+
The main motivation of this RFC is to reserve a new keyword in the 2024 edition.
22
+
The feature used by this keyword described here should be treated as an e-RFC for
23
+
experimentation on nightly with this new keyword. I would like to avoid too much
24
+
discussion of the semantics provided here, and instead discuss the semantics during
25
+
the experimental implementation work.
26
+
21
27
Writing iterators manually can be very painful. Many iterators can be written by
22
28
chaining `Iterator` methods, but some need to be written as a `struct` and have
23
29
`Iterator` implemented for them. Some of the code that is written this way pushes
@@ -167,21 +173,13 @@ It's another language feature for something that can already be written entirely
167
173
We could also use `iter` as a keyword. I would prefer `iter` in because I connect generators with a more powerful
168
174
scheme than just plain `Iterator`s. The `Generator` trait can do everything that `iter` blocks and `async` blocks can do, and more. I believe connecting the `Iterator`
169
175
trait with `iter` blocks is the right choice, but that would require us to carve out many exceptions for this keyword,
170
-
as `iter` is used for module names and method names everywhere (including libstd/libcore).
171
-
172
-
## Contextual keyword
173
-
174
-
We allow `gen` as an identifier for function names and module names, without that conflicting with `gen` blocks, but that makes the syntax more complicated than necessary, for not too much gain.
176
+
as `iter` is used for module names and method names everywhere (including libstd/libcore). It may not be much worse than `gen` (see also [#unresolved-questions])
175
177
176
178
## 2021 edition
177
179
178
180
We could allow `gen` blocks on the 2021 edition via `k#gen {}` syntax.
179
181
We can allow `gen fn` on all editions.
180
182
181
-
## `gen` identifiers on 2024 edition
182
-
183
-
We can allow `i#gen` identifiers in the 2024 edition in order to refer to items named `gen` in previous edition crates.
184
-
185
183
## Do not do this
186
184
187
185
The alternative is to keep adding more helper methods to `Iterator`. It is already rather hard for new Rustaceans to get a hold of all the options they have on `Iterator`.
@@ -210,10 +208,6 @@ def odd_dup(values):
210
208
# Unresolved questions
211
209
[unresolved-questions]: #unresolved-questions
212
210
213
-
- What parts of the design do you expect to resolve through the RFC process before this gets merged?
214
-
- What parts of the design do you expect to resolve through the implementation of this feature before stabilization?
215
-
- What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC?
216
-
217
211
## Panicking
218
212
219
213
What happens when a `gen` block that panicked gets `next` called again? Do we need to poison the iterator?
@@ -222,6 +216,19 @@ What happens when a `gen` block that panicked gets `next` called again? Do we ne
222
216
223
217
Are `gen` blocks fused? Or may they behave eratically after returning `None` the first time?
224
218
219
+
## Contextual keyword
220
+
221
+
Popular crates (like `rand`) have methods called `gen` (https://docs.rs/rand/latest/rand/trait.Rng.html#method.gen). If we forbid those, we are forcing those crates to make a major version bump when they update their edition, and we are requiring any users of those crates to use `r#gen` instead of `gen` when calling that method.
222
+
223
+
We could instead choose to use a contextual keyword and only forbid
224
+
225
+
* bindings,
226
+
* field names (due to destructuring bindings),
227
+
* enum variants,
228
+
* and type names
229
+
230
+
to be `gen`. This should avoid any parsing issues around `gen` followed by `{` in expressions.
231
+
225
232
# Future possibilities
226
233
[future-possibilities]: #future-possibilities
227
234
@@ -254,3 +261,17 @@ We could add a macro to the standard library and prelude, the macro would just e
254
261
```rust
255
262
yield_all!(iter)
256
263
```
264
+
265
+
## Full on `Generator` support
266
+
267
+
We already have a `Generator` trait on nightly that is much more powerful than the `Iterator`
268
+
API could possibly be.
269
+
270
+
1. it uses `Pin<&mut Self>`, allowing self-references in the generator across yield points
271
+
2. it has arguments (`yield` returns the arguments passed to it in the subsequent invocations)
272
+
273
+
Similar (but def not the same) to ideas around `async` closures, I think we could argue for `Generators` to be `gen` closures,
274
+
while `gen` blocks are the simpler concept that has no arguments and just captures variables.
275
+
276
+
Either way, support for full `Generator`s should (in my opinion) be discussed and implemented separately,
277
+
as there are many more open questions around them than around just a simpler way to write `Iterator`s.
0 commit comments