|
|
|
@@ -2,7 +2,7 @@
|
|
|
|
|
<html>
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="utf-8">
|
|
|
|
|
<title>Go by Example: Range over Custom Types</title>
|
|
|
|
|
<title>Go by Example: Range over Iterators</title>
|
|
|
|
|
<link rel=stylesheet href="site.css">
|
|
|
|
|
</head>
|
|
|
|
|
<script>
|
|
|
|
@@ -23,8 +23,8 @@
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
<body>
|
|
|
|
|
<div class="example" id="range-over-custom-types">
|
|
|
|
|
<h2><a href="./">Go by Example</a>: Range over Custom Types</h2>
|
|
|
|
|
<div class="example" id="range-over-iterators">
|
|
|
|
|
<h2><a href="./">Go by Example</a>: Range over Iterators</h2>
|
|
|
|
|
|
|
|
|
|
<table>
|
|
|
|
|
|
|
|
|
@@ -32,7 +32,7 @@
|
|
|
|
|
<td class="docs">
|
|
|
|
|
<p>Starting with version 1.23, Go has added support for
|
|
|
|
|
<a href="https://go.dev/blog/range-functions">iterators</a>,
|
|
|
|
|
which lets us range over custom types.</p>
|
|
|
|
|
which lets us range over pretty much anything!</p>
|
|
|
|
|
|
|
|
|
|
</td>
|
|
|
|
|
<td class="code empty leading">
|
|
|
|
@@ -46,7 +46,7 @@ which lets us range over custom types.</p>
|
|
|
|
|
|
|
|
|
|
</td>
|
|
|
|
|
<td class="code leading">
|
|
|
|
|
<a href="https://go.dev/play/p/q2H-p_moUTy"><img title="Run code" src="play.png" class="run" /></a><img title="Copy code" src="clipboard.png" class="copy" />
|
|
|
|
|
<a href="https://go.dev/play/p/BayyagaCK83"><img title="Run code" src="play.png" class="run" /></a><img title="Copy code" src="clipboard.png" class="copy" />
|
|
|
|
|
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span></span></span></code></pre>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
@@ -147,6 +147,39 @@ return value for a potential early termination.</p>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
|
|
|
|
|
<tr>
|
|
|
|
|
<td class="docs">
|
|
|
|
|
<p>Iteration doesn’t require an underlying data structure,
|
|
|
|
|
and doesn’t even have to be finite! Here’s a function
|
|
|
|
|
returning an iterator over Fibonacci numbers: it keeps
|
|
|
|
|
running as long as <code>yield</code> keeps returning <code>true</code>.</p>
|
|
|
|
|
|
|
|
|
|
</td>
|
|
|
|
|
<td class="code leading">
|
|
|
|
|
|
|
|
|
|
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">genFib</span><span class="p">()</span> <span class="nx">iter</span><span class="p">.</span><span class="nx">Seq</span><span class="p">[</span><span class="kt">int</span><span class="p">]</span> <span class="p">{</span>
|
|
|
|
|
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kd">func</span><span class="p">(</span><span class="nx">yield</span> <span class="kd">func</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span> <span class="kt">bool</span><span class="p">)</span> <span class="p">{</span>
|
|
|
|
|
</span></span><span class="line"><span class="cl"> <span class="nx">a</span><span class="p">,</span> <span class="nx">b</span> <span class="o">:=</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span></span></span></code></pre>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
|
|
|
|
|
<tr>
|
|
|
|
|
<td class="docs">
|
|
|
|
|
|
|
|
|
|
</td>
|
|
|
|
|
<td class="code leading">
|
|
|
|
|
|
|
|
|
|
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">{</span>
|
|
|
|
|
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">!</span><span class="nf">yield</span><span class="p">(</span><span class="nx">a</span><span class="p">)</span> <span class="p">{</span>
|
|
|
|
|
</span></span><span class="line"><span class="cl"> <span class="k">return</span>
|
|
|
|
|
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
|
|
|
|
|
</span></span><span class="line"><span class="cl"> <span class="nx">a</span><span class="p">,</span> <span class="nx">b</span> <span class="p">=</span> <span class="nx">b</span><span class="p">,</span> <span class="nx">a</span><span class="o">+</span><span class="nx">b</span>
|
|
|
|
|
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
|
|
|
|
|
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
|
|
|
|
|
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
|
|
|
|
|
<tr>
|
|
|
|
|
<td class="docs">
|
|
|
|
|
|
|
|
|
@@ -163,8 +196,8 @@ return value for a potential early termination.</p>
|
|
|
|
|
|
|
|
|
|
<tr>
|
|
|
|
|
<td class="docs">
|
|
|
|
|
<p>Since <code>List.All</code> returns an interator, it can be used
|
|
|
|
|
in a regular <code>range</code> loop!</p>
|
|
|
|
|
<p>Since <code>List.All</code> returns an iterator, we can use it
|
|
|
|
|
in a regular <code>range</code> loop.</p>
|
|
|
|
|
|
|
|
|
|
</td>
|
|
|
|
|
<td class="code leading">
|
|
|
|
@@ -183,10 +216,36 @@ For example, <code>Collect</code> takes any iterator and collects
|
|
|
|
|
all its values into a slice.</p>
|
|
|
|
|
|
|
|
|
|
</td>
|
|
|
|
|
<td class="code">
|
|
|
|
|
<td class="code leading">
|
|
|
|
|
|
|
|
|
|
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="nx">all</span> <span class="o">:=</span> <span class="nx">slices</span><span class="p">.</span><span class="nf">Collect</span><span class="p">(</span><span class="nx">lst</span><span class="p">.</span><span class="nf">All</span><span class="p">())</span>
|
|
|
|
|
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">"all:"</span><span class="p">,</span> <span class="nx">all</span><span class="p">)</span>
|
|
|
|
|
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">"all:"</span><span class="p">,</span> <span class="nx">all</span><span class="p">)</span></span></span></code></pre>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
|
|
|
|
|
<tr>
|
|
|
|
|
<td class="docs">
|
|
|
|
|
|
|
|
|
|
</td>
|
|
|
|
|
<td class="code leading">
|
|
|
|
|
|
|
|
|
|
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">n</span> <span class="o">:=</span> <span class="k">range</span> <span class="nf">genFib</span><span class="p">()</span> <span class="p">{</span></span></span></code></pre>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
|
|
|
|
|
<tr>
|
|
|
|
|
<td class="docs">
|
|
|
|
|
<p>Once the loop hits <code>break</code> or an early return, the <code>yield</code> function
|
|
|
|
|
passed to the iterator will return <code>false</code>, stopping the iterator.</p>
|
|
|
|
|
|
|
|
|
|
</td>
|
|
|
|
|
<td class="code">
|
|
|
|
|
|
|
|
|
|
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">n</span> <span class="o">>=</span> <span class="mi">10</span> <span class="p">{</span>
|
|
|
|
|
</span></span><span class="line"><span class="cl"> <span class="k">break</span>
|
|
|
|
|
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
|
|
|
|
|
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">n</span><span class="p">)</span>
|
|
|
|
|
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
|
|
|
|
|
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
@@ -204,7 +263,13 @@ all its values into a slice.</p>
|
|
|
|
|
<pre class="chroma"><code><span class="line"><span class="cl"><span class="go">10
|
|
|
|
|
</span></span></span><span class="line"><span class="cl"><span class="go">13
|
|
|
|
|
</span></span></span><span class="line"><span class="cl"><span class="go">23
|
|
|
|
|
</span></span></span><span class="line"><span class="cl"><span class="go">all: [10 13 23]</span></span></span></code></pre>
|
|
|
|
|
</span></span></span><span class="line"><span class="cl"><span class="go">all: [10 13 23]
|
|
|
|
|
</span></span></span><span class="line"><span class="cl"><span class="go">1
|
|
|
|
|
</span></span></span><span class="line"><span class="cl"><span class="go">1
|
|
|
|
|
</span></span></span><span class="line"><span class="cl"><span class="go">2
|
|
|
|
|
</span></span></span><span class="line"><span class="cl"><span class="go">3
|
|
|
|
|
</span></span></span><span class="line"><span class="cl"><span class="go">5
|
|
|
|
|
</span></span></span><span class="line"><span class="cl"><span class="go">8</span></span></span></code></pre>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
|
|
|
|
@@ -223,7 +288,7 @@ all its values into a slice.</p>
|
|
|
|
|
</div>
|
|
|
|
|
<script>
|
|
|
|
|
var codeLines = [];
|
|
|
|
|
codeLines.push('');codeLines.push('package main\u000A');codeLines.push('import (\u000A \"fmt\"\u000A \"iter\"\u000A \"slices\"\u000A)\u000A');codeLines.push('type List[T any] struct {\u000A head, tail *element[T]\u000A}\u000A');codeLines.push('type element[T any] struct {\u000A next *element[T]\u000A val T\u000A}\u000A');codeLines.push('func (lst *List[T]) Push(v T) {\u000A if lst.tail \u003D\u003D nil {\u000A lst.head \u003D \u0026element[T]{val: v}\u000A lst.tail \u003D lst.head\u000A } else {\u000A lst.tail.next \u003D \u0026element[T]{val: v}\u000A lst.tail \u003D lst.tail.next\u000A }\u000A}\u000A');codeLines.push('func (lst *List[T]) All() iter.Seq[T] {\u000A return func(yield func(T) bool) {\u000A');codeLines.push(' for e :\u003D lst.head; e !\u003D nil; e \u003D e.next {\u000A if !yield(e.val) {\u000A return\u000A }\u000A }\u000A }\u000A}\u000A');codeLines.push('func main() {\u000A lst :\u003D List[int]{}\u000A lst.Push(10)\u000A lst.Push(13)\u000A lst.Push(23)\u000A');codeLines.push(' for e :\u003D range lst.All() {\u000A fmt.Println(e)\u000A }\u000A');codeLines.push(' all :\u003D slices.Collect(lst.All())\u000A fmt.Println(\"all:\", all)\u000A}\u000A');codeLines.push('');
|
|
|
|
|
codeLines.push('');codeLines.push('package main\u000A');codeLines.push('import (\u000A \"fmt\"\u000A \"iter\"\u000A \"slices\"\u000A)\u000A');codeLines.push('type List[T any] struct {\u000A head, tail *element[T]\u000A}\u000A');codeLines.push('type element[T any] struct {\u000A next *element[T]\u000A val T\u000A}\u000A');codeLines.push('func (lst *List[T]) Push(v T) {\u000A if lst.tail \u003D\u003D nil {\u000A lst.head \u003D \u0026element[T]{val: v}\u000A lst.tail \u003D lst.head\u000A } else {\u000A lst.tail.next \u003D \u0026element[T]{val: v}\u000A lst.tail \u003D lst.tail.next\u000A }\u000A}\u000A');codeLines.push('func (lst *List[T]) All() iter.Seq[T] {\u000A return func(yield func(T) bool) {\u000A');codeLines.push(' for e :\u003D lst.head; e !\u003D nil; e \u003D e.next {\u000A if !yield(e.val) {\u000A return\u000A }\u000A }\u000A }\u000A}\u000A');codeLines.push('func genFib() iter.Seq[int] {\u000A return func(yield func(int) bool) {\u000A a, b :\u003D 1, 1\u000A');codeLines.push(' for {\u000A if !yield(a) {\u000A return\u000A }\u000A a, b \u003D b, a+b\u000A }\u000A }\u000A}\u000A');codeLines.push('func main() {\u000A lst :\u003D List[int]{}\u000A lst.Push(10)\u000A lst.Push(13)\u000A lst.Push(23)\u000A');codeLines.push(' for e :\u003D range lst.All() {\u000A fmt.Println(e)\u000A }\u000A');codeLines.push(' all :\u003D slices.Collect(lst.All())\u000A fmt.Println(\"all:\", all)\u000A');codeLines.push(' for n :\u003D range genFib() {\u000A');codeLines.push(' if n \u003E\u003D 10 {\u000A break\u000A }\u000A fmt.Println(n)\u000A }\u000A}\u000A');codeLines.push('');
|
|
|
|
|
</script>
|
|
|
|
|
<script src="site.js" async></script>
|
|
|
|
|
</body>
|