Initial example of range over custom types

This commit is contained in:
Eli Bendersky
2024-08-21 07:04:38 -07:00
parent 6ed788f3f5
commit 2f31c1f6c1
10 changed files with 330 additions and 29 deletions

View File

@@ -22,6 +22,7 @@ Interfaces
Enums
Struct Embedding
Generics
Range over Custom Types
Errors
Custom Errors
Goroutines

View File

@@ -1,2 +1,2 @@
d6b4792fc509f0dcd84f15ed92097f52a73eb877
MNfKskDAZ6d
1ad71763360077271687c5e9d147c89c0b580b0a
7v7vElzhAeO

View File

@@ -0,0 +1,72 @@
// Starting with version 1.23, Go has added support for
// [iterators](https://go.dev/blog/range-functions),
// which lets us range over custom types.
package main
import (
"fmt"
"iter"
"slices"
)
// Let's look at the `List` type from the
// [previous example](generics) again. In that example
// we had an `AllElements` method that returned a slice
// of all elements in the list. With Go iterators, we
// can do it better - as shown below.
type List[T any] struct {
head, tail *element[T]
}
type element[T any] struct {
next *element[T]
val T
}
func (lst *List[T]) Push(v T) {
if lst.tail == nil {
lst.head = &element[T]{val: v}
lst.tail = lst.head
} else {
lst.tail.next = &element[T]{val: v}
lst.tail = lst.tail.next
}
}
// All returns an _iterator_, which in Go is a function
// with a special signature.
func (lst *List[T]) All() iter.Seq[T] {
return func(yield func(T) bool) {
// The iterator function takes another function as
// a parameter, called `yield` by convention (but
// the name can be arbitrary). It will call `yield` for
// every element we want to iterate over, and note `yield`'s
// return value for a potential early termination.
for e := lst.head; e != nil; e = e.next {
if !yield(e.val) {
return
}
}
}
}
func main() {
lst := List[int]{}
lst.Push(10)
lst.Push(13)
lst.Push(23)
// Since `List.All` returns an interator, it can be used
// in a regular `range` loop!
for e := range lst.All() {
fmt.Println(e)
}
// Packages like [slices](https://pkg.go.dev/slices) have
// a number of useful functions to work with iterators.
// For example, `Collect` takes any iterator and collects
// all its values into a slice.
all := slices.Collect(lst.All())
fmt.Println("all:", all)
}

View File

@@ -0,0 +1,2 @@
28edd55763e81476f37e68085f5f79555c15ffe8
Dc3AddmC8Jc

View File

@@ -0,0 +1,5 @@
10
13
23
all: [10 13 23]

2
go.mod
View File

@@ -1,6 +1,6 @@
module github.com/mmcgrana/gobyexample
go 1.22.0
go 1.23.0
require (
github.com/alecthomas/chroma/v2 v2.10.0

2
public/errors generated
View File

@@ -12,7 +12,7 @@
}
if (e.key == "ArrowLeft") {
window.location.href = 'generics';
window.location.href = 'range-over-custom-types';
}

39
public/generics generated
View File

@@ -17,7 +17,7 @@
if (e.key == "ArrowRight") {
window.location.href = 'errors';
window.location.href = 'range-over-custom-types';
}
}
@@ -45,7 +45,7 @@
</td>
<td class="code leading">
<a href="https://go.dev/play/p/MNfKskDAZ6d"><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/7v7vElzhAeO"><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>
@@ -136,11 +136,14 @@ parameters in place. The type is <code>List[T]</code>, not <code>List</code>.</p
<tr>
<td class="docs">
<p>AllElements returns all the List elements as a slice.
In the next example we&rsquo;ll see a more idiomatic way
of iterating over all elements of custom types.</p>
</td>
<td class="code leading">
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">lst</span> <span class="o">*</span><span class="nx">List</span><span class="p">[</span><span class="nx">T</span><span class="p">])</span> <span class="nf">GetAll</span><span class="p">()</span> <span class="p">[]</span><span class="nx">T</span> <span class="p">{</span>
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">lst</span> <span class="o">*</span><span class="nx">List</span><span class="p">[</span><span class="nx">T</span><span class="p">])</span> <span class="nf">AllElements</span><span class="p">()</span> <span class="p">[]</span><span class="nx">T</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">elems</span> <span class="p">[]</span><span class="nx">T</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">e</span> <span class="o">:=</span> <span class="nx">lst</span><span class="p">.</span><span class="nx">head</span><span class="p">;</span> <span class="nx">e</span> <span class="o">!=</span> <span class="kc">nil</span><span class="p">;</span> <span class="nx">e</span> <span class="p">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">next</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">elems</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">elems</span><span class="p">,</span> <span class="nx">e</span><span class="p">.</span><span class="nx">val</span><span class="p">)</span>
@@ -172,7 +175,7 @@ automatically.</p>
</td>
<td class="code leading">
<pre class="chroma"><code><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">&#34;index of foo:&#34;</span><span class="p">,</span> <span class="nf">SlicesIndex</span><span class="p">(</span><span class="nx">s</span><span class="p">,</span> <span class="s">&#34;foo&#34;</span><span class="p">))</span></span></span></code></pre>
<pre class="chroma"><code><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">&#34;index of zoo:&#34;</span><span class="p">,</span> <span class="nf">SlicesIndex</span><span class="p">(</span><span class="nx">s</span><span class="p">,</span> <span class="s">&#34;zoo&#34;</span><span class="p">))</span></span></span></code></pre>
</td>
</tr>
@@ -183,8 +186,7 @@ automatically.</p>
</td>
<td class="code leading">
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="c1">//_ = MapKeys[int, string](m)
</span></span></span></code></pre>
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="nx">_</span> <span class="p">=</span> <span class="nx">SlicesIndex</span><span class="p">[[]</span><span class="kt">string</span><span class="p">,</span> <span class="kt">string</span><span class="p">](</span><span class="nx">s</span><span class="p">,</span> <span class="s">&#34;zoo&#34;</span><span class="p">)</span></span></span></code></pre>
</td>
</tr>
@@ -198,7 +200,7 @@ automatically.</p>
</span></span><span class="line"><span class="cl"> <span class="nx">lst</span><span class="p">.</span><span class="nf">Push</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nx">lst</span><span class="p">.</span><span class="nf">Push</span><span class="p">(</span><span class="mi">13</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nx">lst</span><span class="p">.</span><span class="nf">Push</span><span class="p">(</span><span class="mi">23</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">&#34;list:&#34;</span><span class="p">,</span> <span class="nx">lst</span><span class="p">.</span><span class="nf">GetAll</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">&#34;list:&#34;</span><span class="p">,</span> <span class="nx">lst</span><span class="p">.</span><span class="nf">AllElements</span><span class="p">())</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
</td>
</tr>
@@ -211,32 +213,19 @@ automatically.</p>
<td class="docs">
</td>
<td class="code leading">
<td class="code">
<pre class="chroma"><code><span class="line"><span class="cl"><span class="gp">$</span> go run generics.go
</span></span><span class="line"><span class="cl"><span class="go">keys: [4 1 2]
</span></span><span class="line"><span class="cl"><span class="go">index of zoo: 2
</span></span></span><span class="line"><span class="cl"><span class="go">list: [10 13 23]</span></span></span></code></pre>
</td>
</tr>
<tr>
<td class="docs">
<p>Note: The order of iteration over map keys is not
defined in Go, so different invocations may
result in different orders.</p>
</td>
<td class="code empty">
</td>
</tr>
</table>
<p class="next">
Next example: <a href="errors">Errors</a>.
Next example: <a href="range-over-custom-types">Range over Custom Types</a>.
</p>
@@ -247,7 +236,7 @@ result in different orders.</p>
</div>
<script>
var codeLines = [];
codeLines.push('');codeLines.push('package main\u000A');codeLines.push('import \"fmt\"\u000A');codeLines.push('func SlicesIndex[S ~[]E, E comparable](s S, v E) int {\u000A for i :\u003D range s {\u000A if v \u003D\u003D s[i] {\u000A return i\u000A }\u000A }\u000A return -1\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]) GetAll() []T {\u000A var elems []T\u000A for e :\u003D lst.head; e !\u003D nil; e \u003D e.next {\u000A elems \u003D append(elems, e.val)\u000A }\u000A return elems\u000A}\u000A');codeLines.push('func main() {\u000A var s \u003D []string{\"foo\", \"bar\", \"zoo\"}\u000A');codeLines.push(' fmt.Println(\"index of foo:\", SlicesIndex(s, \"foo\"))\u000A');codeLines.push(' //_ \u003D MapKeys[int, string](m)\u000A');codeLines.push(' lst :\u003D List[int]{}\u000A lst.Push(10)\u000A lst.Push(13)\u000A lst.Push(23)\u000A fmt.Println(\"list:\", lst.GetAll())\u000A}\u000A');codeLines.push('');codeLines.push('');
codeLines.push('');codeLines.push('package main\u000A');codeLines.push('import \"fmt\"\u000A');codeLines.push('func SlicesIndex[S ~[]E, E comparable](s S, v E) int {\u000A for i :\u003D range s {\u000A if v \u003D\u003D s[i] {\u000A return i\u000A }\u000A }\u000A return -1\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]) AllElements() []T {\u000A var elems []T\u000A for e :\u003D lst.head; e !\u003D nil; e \u003D e.next {\u000A elems \u003D append(elems, e.val)\u000A }\u000A return elems\u000A}\u000A');codeLines.push('func main() {\u000A var s \u003D []string{\"foo\", \"bar\", \"zoo\"}\u000A');codeLines.push(' fmt.Println(\"index of zoo:\", SlicesIndex(s, \"zoo\"))\u000A');codeLines.push(' _ \u003D SlicesIndex[[]string, string](s, \"zoo\")\u000A');codeLines.push(' lst :\u003D List[int]{}\u000A lst.Push(10)\u000A lst.Push(13)\u000A lst.Push(23)\u000A fmt.Println(\"list:\", lst.AllElements())\u000A}\u000A');codeLines.push('');
</script>
<script src="site.js" async></script>
</body>

2
public/index.html generated
View File

@@ -81,6 +81,8 @@
<li><a href="generics">Generics</a></li>
<li><a href="range-over-custom-types">Range over Custom Types</a></li>
<li><a href="errors">Errors</a></li>
<li><a href="custom-errors">Custom Errors</a></li>

230
public/range-over-custom-types generated Normal file
View File

@@ -0,0 +1,230 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Go by Example: Range over Custom Types</title>
<link rel=stylesheet href="site.css">
</head>
<script>
window.onkeydown = (e) => {
if (e.ctrlKey || e.altKey || e.shiftKey) {
return;
}
if (e.key == "ArrowLeft") {
window.location.href = 'generics';
}
if (e.key == "ArrowRight") {
window.location.href = 'errors';
}
}
</script>
<body>
<div class="example" id="range-over-custom-types">
<h2><a href="./">Go by Example</a>: Range over Custom Types</h2>
<table>
<tr>
<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>
</td>
<td class="code empty leading">
</td>
</tr>
<tr>
<td class="docs">
</td>
<td class="code leading">
<a href="https://go.dev/play/p/Dc3AddmC8Jc"><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>
<tr>
<td class="docs">
</td>
<td class="code leading">
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">&#34;fmt&#34;</span>
</span></span><span class="line"><span class="cl"> <span class="s">&#34;iter&#34;</span>
</span></span><span class="line"><span class="cl"> <span class="s">&#34;slices&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span></span></span></code></pre>
</td>
</tr>
<tr>
<td class="docs">
<p>Let&rsquo;s look at the <code>List</code> type from the
<a href="generics">previous example</a> again. In that example
we had an <code>AllElements</code> method that returned a slice
of all elements in the list. With Go iterators, we
can do it better - as shown below.</p>
</td>
<td class="code leading">
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">List</span><span class="p">[</span><span class="nx">T</span> <span class="nx">any</span><span class="p">]</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">head</span><span class="p">,</span> <span class="nx">tail</span> <span class="o">*</span><span class="nx">element</span><span class="p">[</span><span class="nx">T</span><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">
</td>
<td class="code leading">
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">element</span><span class="p">[</span><span class="nx">T</span> <span class="nx">any</span><span class="p">]</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">next</span> <span class="o">*</span><span class="nx">element</span><span class="p">[</span><span class="nx">T</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"> <span class="nx">val</span> <span class="nx">T</span>
</span></span><span class="line"><span class="cl"><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="kd">func</span> <span class="p">(</span><span class="nx">lst</span> <span class="o">*</span><span class="nx">List</span><span class="p">[</span><span class="nx">T</span><span class="p">])</span> <span class="nf">Push</span><span class="p">(</span><span class="nx">v</span> <span class="nx">T</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">lst</span><span class="p">.</span><span class="nx">tail</span> <span class="o">==</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">lst</span><span class="p">.</span><span class="nx">head</span> <span class="p">=</span> <span class="o">&amp;</span><span class="nx">element</span><span class="p">[</span><span class="nx">T</span><span class="p">]{</span><span class="nx">val</span><span class="p">:</span> <span class="nx">v</span><span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">lst</span><span class="p">.</span><span class="nx">tail</span> <span class="p">=</span> <span class="nx">lst</span><span class="p">.</span><span class="nx">head</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">lst</span><span class="p">.</span><span class="nx">tail</span><span class="p">.</span><span class="nx">next</span> <span class="p">=</span> <span class="o">&amp;</span><span class="nx">element</span><span class="p">[</span><span class="nx">T</span><span class="p">]{</span><span class="nx">val</span><span class="p">:</span> <span class="nx">v</span><span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">lst</span><span class="p">.</span><span class="nx">tail</span> <span class="p">=</span> <span class="nx">lst</span><span class="p">.</span><span class="nx">tail</span><span class="p">.</span><span class="nx">next</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">
<p>All returns an <em>iterator</em>, which in Go is a function
with a special signature.</p>
</td>
<td class="code leading">
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">lst</span> <span class="o">*</span><span class="nx">List</span><span class="p">[</span><span class="nx">T</span><span class="p">])</span> <span class="nf">All</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="nx">T</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="nx">T</span><span class="p">)</span> <span class="kt">bool</span><span class="p">)</span> <span class="p">{</span></span></span></code></pre>
</td>
</tr>
<tr>
<td class="docs">
<p>The iterator function takes another function as
a parameter, called <code>yield</code> by convention (but
the name can be arbitrary). It will call <code>yield</code> for
every element we want to iterate over, and note <code>yield</code>&rsquo;s
return value for a potential early termination.</p>
</td>
<td class="code leading">
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">e</span> <span class="o">:=</span> <span class="nx">lst</span><span class="p">.</span><span class="nx">head</span><span class="p">;</span> <span class="nx">e</span> <span class="o">!=</span> <span class="kc">nil</span><span class="p">;</span> <span class="nx">e</span> <span class="p">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">next</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">e</span><span class="p">.</span><span class="nx">val</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="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">
</td>
<td class="code leading">
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">lst</span> <span class="o">:=</span> <span class="nx">List</span><span class="p">[</span><span class="kt">int</span><span class="p">]{}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">lst</span><span class="p">.</span><span class="nf">Push</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nx">lst</span><span class="p">.</span><span class="nf">Push</span><span class="p">(</span><span class="mi">13</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nx">lst</span><span class="p">.</span><span class="nf">Push</span><span class="p">(</span><span class="mi">23</span><span class="p">)</span></span></span></code></pre>
</td>
</tr>
<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>
</td>
<td class="code leading">
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">e</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">lst</span><span class="p">.</span><span class="nf">All</span><span class="p">()</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="nx">e</span><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">
<p>Packages like <a href="https://pkg.go.dev/slices">slices</a> have
a number of useful functions to work with iterators.
For example, <code>Collect</code> takes any iterator and collects
all its values into a slice.</p>
</td>
<td class="code">
<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">&#34;all:&#34;</span><span class="p">,</span> <span class="nx">all</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
</td>
</tr>
</table>
<table>
<tr>
<td class="docs">
</td>
<td class="code">
<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>
</td>
</tr>
</table>
<p class="next">
Next example: <a href="errors">Errors</a>.
</p>
<p class="footer">
by <a href="https://markmcgranaghan.com">Mark McGranaghan</a> and <a href="https://eli.thegreenplace.net">Eli Bendersky</a> | <a href="https://github.com/mmcgrana/gobyexample">source</a> | <a href="https://github.com/mmcgrana/gobyexample#license">license</a>
</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('');
</script>
<script src="site.js" async></script>
</body>
</html>