Skip to content

Commit

Permalink
spec: document for range loop over functions
Browse files Browse the repository at this point in the history
For #61405.
Fixes #65237.

Change-Id: Ia7820c0ef089c828ea7ed3d2802c5185c945290e
Reviewed-on: https://go-review.googlesource.com/c/go/+/589397
TryBot-Bypass: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
  • Loading branch information
griesemer authored and gopherbot committed Jun 4, 2024
1 parent 200b280 commit 535f81e
Showing 1 changed file with 37 additions and 7 deletions.
44 changes: 37 additions & 7 deletions doc/go_spec.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
"Subtitle": "Language version go1.22 (April 25, 2024)",
"Subtitle": "Language version go1.23 (June 4, 2024)",
"Path": "/ref/spec"
}-->

Expand Down Expand Up @@ -6656,13 +6656,16 @@ <h4 id="For_range">For statements with <code>range</code> clause</h4>
</p>

<pre class="grammar">
Range expression 1st value 2nd value
Range expression 1st value 2nd value

array or slice a [n]E, *[n]E, or []E index i int a[i] E
string s string type index i int see below rune
map m map[K]V key k K m[k] V
channel c chan E, &lt;-chan E element e E
integer value n integer type, or untyped int value i see below
array or slice a [n]E, *[n]E, or []E index i int a[i] E
string s string type index i int see below rune
map m map[K]V key k K m[k] V
channel c chan E, &lt;-chan E element e E
integer value n integer type, or untyped int value i see below
function, 0 values f func(func() bool)
function, 1 value f func(func(V) bool) value v V
function, 2 values f func(func(K, V) bool) key k K v V
</pre>

<ol>
Expand Down Expand Up @@ -6716,6 +6719,23 @@ <h4 id="For_range">For statements with <code>range</code> clause</h4>
the type of the iteration values is the <a href="#Constants">default type</a> for <code>n</code>.
If <code>n</code> &lt= 0, the loop does not run any iterations.
</li>

<li>
For a function <code>f</code>, the iteration proceeds by calling <code>f</code>
with a new, synthesized <code>yield</code> function as its argument.
If <code>yield</code> is called before <code>f</code> returns,
the arguments to <code>yield</code> become the iteration values
for executing the loop body once.
After each successive loop iteration, <code>yield</code> returns true
and may be called again to continue the loop.
As long as the loop body does not terminate, the "range" clause will continue
to generate iteration values this way for each <code>yield</code> call until
<code>f</code> returns.
If the loop body terminates (such as by a <code>break</code> statement),
<code>yield</code> returns false and must not be called again.
The number of iteration variables must match the number and order of arguments
to <code>yield</code>.
</li>
</ol>

<p>
Expand Down Expand Up @@ -6784,6 +6804,16 @@ <h4 id="For_range">For statements with <code>range</code> clause</h4>
// invalid: 1e3 is a floating-point constant
for range 1e3 {
}
<!-- TODO(gri) need better examples for range-over-func -->
// print hello world
f := func(yield func(string) bool) {
if yield("hello") {
yield("world")
}
}
for word := range f {
println(word)
}
</pre>


Expand Down

0 comments on commit 535f81e

Please sign in to comment.