List of Constraint - text.Baldanders.info
tag:text.Baldanders.info,2020-09-26:/tags
2020-09-26T23:21:12+09:00
帰ってきた「しっぽのさきっちょ」
https://text.baldanders.info/images/avatar.jpg
https://text.baldanders.info/images/avatar.jpg
次期 Go 言語で導入される総称型について予習する(その3)
tag:text.Baldanders.info,2020-09-26:/golang/generics-in-go-2-update-update/
2020-09-26T14:21:12+00:00
2021-12-04T02:40:05+00:00
Go が総称型を得ることで更に独自に発展することを期待している。
Spiegel
https://baldanders.info/profile/
<div class="box"><strong>【2021-02-21 追記】</strong>
型パラメータの提案(「総称型」というのは厳密には正しくないらしい)は2021年2月に承認され,製造フェーズに入ったようだ。</div>
<ol>
<li><a href="https://text.baldanders.info/golang/generics-in-go-2/">次期 Go 言語で導入される(かもしれない)総称型について予習する</a></li>
<li><a href="https://text.baldanders.info/golang/generics-in-go-2-update/">次期 Go 言語で導入される総称型について予習する(その2)</a></li>
<li><a href="https://text.baldanders.info/golang/generics-in-go-2-update-update/">次期 Go 言語で導入される総称型について予習する(その3)</a> ←イマココ</li>
</ol>
<hr>
<p><a href="https://text.baldanders.info/golang/generics-in-go-2-update/" title="次期 Go 言語で導入される総称型について予習する(その2)">前回</a>紹介した “<a href="https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md">Type Parameters - Draft Design</a>” が 2020-09-21 にアップデートされたらしい(最終更新:2020-11-25)。
どうやらこれが最終案になりそうだ。</p>
<p>早ければ2021年8月にリリース予定の <a href="https://go.dev/">Go</a> 1.17 で<a href="https://blog.golang.org/generics-next-step" title="The Next Step for Generics - The Go Blog">お披露目</a>というスケジュールは変わらない模様。
また総称型(generics)に対応した Playground も最終案の仕様で稼働中である。</p>
<ul>
<li><a href="https://go2goplay.golang.org/"><code>https://go2goplay.golang.org/</code></a></li>
</ul>
<h2>前回からの変更点</h2>
<p><a href="https://text.baldanders.info/golang/generics-in-go-2-update/" title="次期 Go 言語で導入される総称型について予習する(その2)">前回</a>は,たとえば</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">ordered</span> <span class="kd">interface</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">type</span> <span class="kt">int</span><span class="p">,</span> <span class="kt">int8</span><span class="p">,</span> <span class="kt">int16</span><span class="p">,</span> <span class="kt">int32</span><span class="p">,</span> <span class="kt">int64</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="kt">uint</span><span class="p">,</span> <span class="kt">uint8</span><span class="p">,</span> <span class="kt">uint16</span><span class="p">,</span> <span class="kt">uint32</span><span class="p">,</span> <span class="kt">uint64</span><span class="p">,</span> <span class="kt">uintptr</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="kt">float32</span><span class="p">,</span> <span class="kt">float64</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="kt">string</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">Max</span><span class="p">(</span><span class="kd">type</span> <span class="nx">T</span> <span class="nx">ordered</span><span class="p">)(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span> <span class="nx">T</span><span class="p">)</span> <span class="nx">T</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">x</span> <span class="p"><</span> <span class="nx">y</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">y</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">x</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>のような記述だったが,今回は型パラメータ(type parameter)の記述がちょっと変わったようで</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">ordered</span> <span class="kd">interface</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">type</span> <span class="kt">int</span><span class="p">,</span> <span class="kt">int8</span><span class="p">,</span> <span class="kt">int16</span><span class="p">,</span> <span class="kt">int32</span><span class="p">,</span> <span class="kt">int64</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="kt">uint</span><span class="p">,</span> <span class="kt">uint8</span><span class="p">,</span> <span class="kt">uint16</span><span class="p">,</span> <span class="kt">uint32</span><span class="p">,</span> <span class="kt">uint64</span><span class="p">,</span> <span class="kt">uintptr</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="kt">float32</span><span class="p">,</span> <span class="kt">float64</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="kt">string</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line hl"><span class="cl"><span class="kd">func</span> <span class="nx">Max</span><span class="p">[</span><span class="nx">T</span> <span class="nx">ordered</span><span class="p">](</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span> <span class="nx">T</span><span class="p">)</span> <span class="nx">T</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">x</span> <span class="p"><</span> <span class="nx">y</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">y</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">x</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>と角括弧 <code>[...]</code> で囲まれている。
どうしても山括弧 <code><...></code> はイヤみたい(笑)</p>
<p><code>type</code> キーワードは無用となった。</p>
<h2>組込み済みの制約</h2>
<p>組込み済みの interface 型として <code>error</code> が定義されているように,組込み済みの制約(constraint)として <code>any</code> と <code>comparable</code> が追加されるようだ。</p>
<p><code>any</code> はあらゆる型を包摂する。
むしろ「制約がない」ことを示す制約というべきか。
強いて書くなら</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">any</span> <span class="kd">interface</span><span class="p">{}</span>
</span></span></code></pre></div><p>といったところだろうか。
たとえば</p>
<figure lang="en">
<blockquote class="nobox"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">// Print prints the elements of any slice.
</span></span></span><span class="line"><span class="cl"><span class="c1">// Print has a type parameter T and has a single (non-type)
</span></span></span><span class="line"><span class="cl"><span class="c1">// parameter s which is a slice of that type parameter.
</span></span></span><span class="line hl"><span class="cl"><span class="c1"></span><span class="kd">func</span> <span class="nx">Print</span><span class="p">[</span><span class="nx">T</span> <span class="nx">any</span><span class="p">](</span><span class="nx">s</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">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">v</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">s</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">v</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></div></blockquote>
<figcaption><div>via <q><a href="https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md">Type Parameters - Draft Design</a></q></div></figcaption>
</figure>
<p>みたいな感じに使える。
どうやら型パラメータの指定で制約を省略することはできないようなので,制約がない場合は <code>any</code> を付けることになりそうだ。</p>
<p><code>comparable</code> は演算子 <code>==</code> および <code>!==</code> が使える型を示す制約だ。
これを使って</p>
<figure lang="en">
<blockquote class="nobox"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="s">"fmt"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line hl"><span class="cl"><span class="kd">func</span> <span class="nx">Contains</span><span class="p">[</span><span class="nx">T</span> <span class="nx">comparable</span><span class="p">](</span><span class="nx">col</span> <span class="p">[]</span><span class="nx">T</span><span class="p">,</span> <span class="nx">item</span> <span class="nx">T</span><span class="p">)</span> <span class="kt">bool</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">e</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">col</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">e</span> <span class="o">==</span> <span class="nx">item</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">true</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="k">return</span> <span class="kc">false</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><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">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nf">Contains</span><span class="p">([]</span><span class="kt">string</span><span class="p">{</span><span class="s">"coffee"</span><span class="p">,</span> <span class="s">"tea"</span><span class="p">},</span> <span class="s">"coffee"</span><span class="p">))</span> <span class="c1">//true
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nf">Contains</span><span class="p">([]</span><span class="kt">int</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">},</span> <span class="mi">11</span><span class="p">))</span> <span class="c1">//false
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nf">Contains</span><span class="p">([]</span><span class="kt">int</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">},</span> <span class="mi">1</span><span class="p">))</span> <span class="c1">//true
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span></code></pre></div></blockquote>
<figcaption><div>via <q><a href="https://blog.yongweilun.me/go-generics-draft-design-final">Go Generics draft design Final</a></q></div></figcaption>
</figure>
<p>のように書ける。</p>
<p><code>any</code> も <code>comparable</code> も制約としてのみ使用可能で,通常の inteface 型としては使えないようだ。</p>
<p>なお, <a href="https://go.dev/">Go</a> の総称型について詳しくは以下の「本」がオススメである。
色々な事例が載っているのでかなり参考になる。</p>
<ul>
<li><a href="https://zenn.dev/mattn/books/4c7de85ec42cb44cf285">Go 言語にやってくる Generics は我々に何をもたらすのか | Zenn</a></li>
</ul>
<p>この本を買うために <a href="https://zenn.dev/">Zenn</a> のアカウントを取ってもいいかも(クレカが通ればだけど)。</p>
<h2><a href="https://go.dev/">Go</a> は Nearly Java になるか</h2>
<p>上述の「本」に</p>
<figure>
<blockquote>
<q>その慎重な Go が今、Generics を取り入れ、Better C から Nearly Java へと変わろうとしています。Java がそうであった様に、Go は Generics の導入により多くのアルゴリズムが汎用的に実装され便利になっていくでしょう</q>
</blockquote>
<figcaption><div><q><a href="https://zenn.dev/mattn/books/4c7de85ec42cb44cf285">Go 言語にやってくる Generics は我々に何をもたらすのか</a></q>より</div></figcaption>
</figure>
<p>とある。
標準の <a href="https://golang.org/pkg/sort/" title="sort - The Go Programming Language"><code>sort</code></a> パッケージのように型ごとに似たようなコードをゴリゴリ書くのではなく,汎化されたアルゴリズムに集約されていく期待感はあるが,それが Nearly Java になるかについては懐疑的である。</p>
<p><a href="https://go.dev/">Go 言語</a>の特徴のひとつは「汎化」の実装として Java や Rust のような公称型の部分型付け(nominal subtyping)ではなく構造型の部分型付け(structural subtyping)を採用していることにある。
当然ながらこれは総称型を使ったアルゴリズムの実装にも大きな影響を与える筈である。</p>
<p>私は <a href="https://go.dev/">Go</a> が総称型を得ることで更に独自に発展することを期待している。</p>
<h2>ブックマーク</h2>
<ul>
<li>
<p><a href="https://blog.yongweilun.me/go-generics-draft-design-final?guid=none&deviceId=0389b3ed-c102-4f48-ba65-49e5f54124a4">Go Generics draft design Final</a></p>
</li>
<li>
<p><a href="https://zenn.dev/shuyo/books/4536b976e169ca">Go: Type Parameters - Draft Design 抄訳</a></p>
</li>
<li>
<p><a href="https://text.baldanders.info/remark/2020/04/subtyping/">それは Duck Typing ぢゃない(らしい)</a></p>
</li>
</ul>
<h2>参考図書</h2>
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/416Stewy0NS._SL160_.jpg" width="123" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">プログラミング言語Go</a></dt>
<dd>アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)</dd>
<dd>丸善出版 2016-06-20 (Release 2021-07-13)</dd>
<dd>Kindle版</dd>
<dd>B099928SJD (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想は<a href="https://text.baldanders.info/remark/2016/07/go-programming-language/" >こちら</a>。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2021-05-22">2021-05-22</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- プログラミング言語Go -->
次期 Go 言語で導入される総称型について予習する(その2)
tag:text.Baldanders.info,2020-06-17:/golang/generics-in-go-2-update/
2020-06-17T07:33:04+00:00
2021-12-04T02:40:05+00:00
総称型について仕様が変わったらしい。早ければ2021年8月のリリースでお披露目されるかもしれないとのこと。
Spiegel
https://baldanders.info/profile/
<div class="box"><strong>【2021-02-21 追記】</strong>
型パラメータの提案(「総称型」というのは厳密には正しくないらしい)は2021年2月に承認され,製造フェーズに入ったようだ。</div>
<ol>
<li><a href="https://text.baldanders.info/golang/generics-in-go-2/">次期 Go 言語で導入される(かもしれない)総称型について予習する</a></li>
<li><a href="https://text.baldanders.info/golang/generics-in-go-2-update/">次期 Go 言語で導入される総称型について予習する(その2)</a> ←イマココ</li>
<li><a href="https://text.baldanders.info/golang/generics-in-go-2-update-update/">次期 Go 言語で導入される総称型について予習する(その3)</a></li>
</ol>
<hr>
<p>以前書いた<a href="https://text.baldanders.info/golang/generics-in-go-2/" title="次期 Go 言語で導入される(かもしれない)総称型について予習する">記事</a>に関して,仕様が変わったらしい。</p>
<ul>
<li><a href="https://blog.golang.org/generics-next-step">The Next Step for Generics - The Go Blog</a></li>
<li><a href="https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md">Type Parameters - Draft Design</a></li>
</ul>
<p>そこで,これまでのおさらいと変更点について簡単に紹介する。</p>
<h2>「総称型」のおさらい</h2>
<p>次期 <a href="https://golang.org/" title="The Go Programming Language">Go 言語</a>で導入される「総称型(generics)」について,これまで提案されていた仕様は以下の通り。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="nx">contract</span> <span class="nf">ordered</span><span class="p">(</span><span class="nx">t</span> <span class="nx">T</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">t</span> <span class="p"><</span> <span class="nx">t</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">Max</span><span class="p">(</span><span class="kd">type</span> <span class="nx">T</span> <span class="nx">ordered</span><span class="p">)(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span> <span class="nx">T</span><span class="p">)</span> <span class="nx">T</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">x</span> <span class="p"><</span> <span class="nx">y</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">y</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">x</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p><code>Max()</code> 関数の <code>(type T ordered)</code> の部分が「型パラメータ(type parameter)」で,これによって型 <code>T</code> が総称型であることを示す。
また <code>ordered</code> は「型コントラクト(type contract)」と呼ばれ,総称型に対する制約(constraint)として機能している。</p>
<h2>制約の定義</h2>
<p>新しい提案では,型コントラクトを捨て,制約の定義を以下のように変更する。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line hl"><span class="cl"><span class="kd">type</span> <span class="nx">ordered</span> <span class="kd">interface</span> <span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="kd">type</span> <span class="kt">int</span><span class="p">,</span> <span class="kt">int8</span><span class="p">,</span> <span class="kt">int16</span><span class="p">,</span> <span class="kt">int32</span><span class="p">,</span> <span class="kt">int64</span><span class="p">,</span>
</span></span><span class="line hl"><span class="cl"> <span class="kt">uint</span><span class="p">,</span> <span class="kt">uint8</span><span class="p">,</span> <span class="kt">uint16</span><span class="p">,</span> <span class="kt">uint32</span><span class="p">,</span> <span class="kt">uint64</span><span class="p">,</span> <span class="kt">uintptr</span><span class="p">,</span>
</span></span><span class="line hl"><span class="cl"> <span class="kt">float32</span><span class="p">,</span> <span class="kt">float64</span><span class="p">,</span>
</span></span><span class="line hl"><span class="cl"> <span class="kt">string</span>
</span></span><span class="line hl"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">Max</span><span class="p">(</span><span class="kd">type</span> <span class="nx">T</span> <span class="nx">ordered</span><span class="p">)(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span> <span class="nx">T</span><span class="p">)</span> <span class="nx">T</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">x</span> <span class="p"><</span> <span class="nx">y</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">y</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">x</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>以前の型コントラクトとの違いは <strong>既存のキーワードがそのまま使える</strong> ことである。
文法も <code>interface</code> 型の宣言とほぼ同じだが <code>type int, int8, ...</code> といった感じに型の列挙ができる点がこれまでと異なる。</p>
<p>これにより,制約 <code>ordered</code> を満たす型であれば</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><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">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nf">Max</span><span class="p">(</span><span class="nf">Max</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="mi">3</span><span class="p">))</span> <span class="c1">//Output: 3
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">"%#U\n"</span><span class="p">,</span> <span class="nf">Max</span><span class="p">(</span><span class="nf">Max</span><span class="p">(</span><span class="sc">'あ'</span><span class="p">,</span> <span class="sc">'い'</span><span class="p">),</span> <span class="mi">0</span><span class="p">))</span> <span class="c1">//Output: U+3044 'い'
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span></code></pre></div><p>などと記述できる。</p>
<p>なお,これまでの <code>interface</code> 型も制約として使える。
たとえば,こんな感じ。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">SayError</span><span class="p">(</span><span class="kd">type</span> <span class="nx">E</span> <span class="kt">error</span><span class="p">)(</span><span class="nx">e</span> <span class="nx">E</span><span class="p">)</span> <span class="kt">string</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">e</span><span class="p">.</span><span class="nf">Error</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></span><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">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nf">SayError</span><span class="p">(</span><span class="nx">io</span><span class="p">.</span><span class="nx">EOF</span><span class="p">))</span> <span class="c1">//Output: EOF
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span></code></pre></div><p>更に <code>interface</code> 型を入れ子にすることで複雑な制約条件を構成することもできる。</p>
<h2>注入するか単態化するか</h2>
<p>ところで先程の</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">SayError</span><span class="p">(</span><span class="kd">type</span> <span class="nx">E</span> <span class="kt">error</span><span class="p">)(</span><span class="nx">e</span> <span class="nx">E</span><span class="p">)</span> <span class="kt">string</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">e</span><span class="p">.</span><span class="nf">Error</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>は,わざわざ総称型を使わなくとも今までの書き方で</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">SayError</span><span class="p">(</span><span class="nx">e</span> <span class="kt">error</span><span class="p">)</span> <span class="kt">string</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">e</span><span class="p">.</span><span class="nf">Error</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>としても見た目の結果は同じになる。</p>
<p>しかし,今までの書き方が実行時に動的ディスパッチを行う「依存の注入(depencency injection)」であるのに対し,総称型を使った記述はコンパイル時に型ごとに別々の関数として展開される。
これを「単態化(monomorphization)」と呼ぶ。</p>
<p>依存の注入と単態化ではリソース管理の戦略がまるで異なる。</p>
<p>たとえば上述の <code>SayError()</code> 関数を総称型で記述するのは,どう考えても効率が悪い。
<code>error</code> に包摂される型は必要に応じていくらでも定義可能であり,それらの型ごとに単態化されるなどぞんぞがさばる。</p>
<p>逆に <code>Max()</code> 関数なんかは,基本型の振る舞いを <code>interface</code> で括るのが難しいこともあり,コストの高い <code>float64</code> 型の <a href="https://pkg.go.dev/math" title="math package · pkg.go.dev"><code>math</code></a><code>.Max()</code> くらいしか標準では実装されてなかったりする。
こういったものを総称型で記述できるようになれば(OAOO 原則の観点から考えても)コード管理しやすくなるだろう。</p>
<p>「<a href="https://slide.baldanders.info/shimane-go-2020-01-23/">Go プログラマは息をするように依存を注入する</a>」。
他のプログラミング言語が総称型で書いているかなりの部分を依存の注入で簡単に纏めてしまえるのが <a href="https://golang.org/" title="The Go Programming Language">Go 言語</a>の強みであるが,使える道具は多いに越したことはない。</p>
<h2><a href="https://go.dev/">Go</a> 2 Playground</h2>
<p>次期 <a href="https://golang.org/" title="The Go Programming Language">Go 言語</a>用に新しい Playground が公開されている。</p>
<ul>
<li><a href="https://go2goplay.golang.org/"><code>https://go2goplay.golang.org/</code></a></li>
</ul>
<p>総称型についてもここで色々と試せるようなので,遊びに行ってみてはいかがだろうか。</p>
<h2>早ければ <a href="https://go.dev/">Go</a> 1.17 でお披露目?</h2>
<p>だいぶ仕様が固まってきた総称型であるが,早ければ2021年8月にリリース予定の <a href="https://go.dev/">Go</a> 1.17 で<a href="https://blog.golang.org/generics-next-step" title="The Next Step for Generics - The Go Blog">お披露目されるかもしれない</a>とのこと。</p>
<p>たのしみ!</p>
<h2>ブックマーク</h2>
<ul>
<li><a href="https://www.pixelstech.net/article/1559993656-Why-no-max-min-function-for-integer-in-GoLang">Why no max/min function for integer in GoLang | Pixelstech.net</a></li>
<li><a href="https://text.baldanders.info/remark/2020/04/subtyping/">それは Duck Typing ぢゃない(らしい)</a></li>
</ul>
<h2>参考図書</h2>
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/416Stewy0NS._SL160_.jpg" width="123" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">プログラミング言語Go</a></dt>
<dd>アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)</dd>
<dd>丸善出版 2016-06-20 (Release 2021-07-13)</dd>
<dd>Kindle版</dd>
<dd>B099928SJD (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想は<a href="https://text.baldanders.info/remark/2016/07/go-programming-language/" >こちら</a>。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2021-05-22">2021-05-22</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- プログラミング言語Go -->