List of Variable-Bindings - text.Baldanders.info
tag:text.Baldanders.info,2020-03-01:/tags
2020-03-01T21:08:53+09:00
帰ってきた「しっぽのさきっちょ」
https://text.baldanders.info/images/avatar.jpg
https://text.baldanders.info/images/avatar.jpg
変数束縛
tag:text.Baldanders.info,2020-03-01:/rust-lang/variable-bindings/
2020-03-01T12:08:53+00:00
2021-04-24T09:37:24+00:00
「値」は所有者である「変数」に束縛される。
Spiegel
https://baldanders.info/profile/
<p><a href="https://www.rust-lang.org/" title="Rust Programming Language">Rust</a> の所有権(ownership)のルールは以下の3つ(公式ドキュメントの「<a href="https://doc.rust-jp.rs/book/second-edition/ch04-01-what-is-ownership.html" title="所有権とは? - The Rust Programming Language">所有権とは?</a>」より抜粋)。</p>
<ol>
<li><a href="https://www.rust-lang.org/" title="Rust Programming Language">Rust</a> の各値は、所有者と呼ばれる変数と対応している</li>
<li>いかなる時も所有者は一つである</li>
<li>所有者がスコープから外れたら、値は破棄される</li>
</ol>
<p>「値」は所有者である「変数」に束縛される。
これを「変数束縛(variable bindings)」と呼ぶ。</p>
<p>実際に変数束縛がどのように機能しているかを見てみよう。</p>
<h2>Copy Semantics</h2>
<p><a href="https://www.rust-lang.org/" title="Rust Programming Language">Rust</a> において組み込みで定義されるデータ型は以下の通り。</p>
<ul>
<li>スカラ型
<ul>
<li>整数 (<code>i8</code>, <code>u8</code>, …, <code>isize</code>, <code>usize</code>)</li>
<li>浮動小数点数型(<code>f32</code>, <code>f64</code>)</li>
<li>論理値型(<code>bool</code>)</li>
<li>文字型(<code>char</code>): Unicode 符号点</li>
</ul>
</li>
<li>複合型
<ul>
<li>タプル型</li>
<li>配列型</li>
</ul>
</li>
</ul>
<p>(詳しくは「<a href="https://text.baldanders.info/rust-lang/types/">型に関する覚え書き</a>」を参照のこと)</p>
<p>スカラ型およびスカラ型で構成される複合型は値と変数が一体になっていて(値が固定長で直接スタックに積まれるため),代入時に値のコピーが発生する。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">ary1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="p">];</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">ary2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ary1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">ary1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">*=</span><span class="w"> </span><span class="mi">100</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"ary1 = </span><span class="si">{:?}</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">ary1</span><span class="p">);</span><span class="w"> </span><span class="c1">//Output: ary1 = [100, 2, 3]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"ary2 = </span><span class="si">{:?}</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">ary2</span><span class="p">);</span><span class="w"> </span><span class="c1">//Output: ary2 = [1, 2, 3]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>イメージとしてはこんな感じ。</p>
<figure style='margin:0 auto;text-align:center;'><div class="lightmode"><a href="./array.svg"><img src="./array.png" srcset="./array.png 500w" sizes="(min-width:600px) 500px, 80vw" alt="" loading="lazy"></a></figure>
<p>このようにデータ型では値をコピーすることによって変数束縛を担保している。</p>
<p>ちなみに <code>mut</code> は変数が可変(mutable)であることを示す。
<a href="https://www.rust-lang.org/" title="Rust Programming Language">Rust</a> では,全ての変数は宣言時に <code>mut</code> キーワードを付けない限り不変(immutable)である。</p>
<h2>Move Semantics</h2>
<p><a href="https://www.rust-lang.org/" title="Rust Programming Language">Rust</a> には上述のデータ型以外にもいくつかの型が存在する。
以下に主なものを挙げる。</p>
<ul>
<li>構造体(<code>struct</code>)</li>
<li>コレクション
<ul>
<li>文字列(<code>String</code>)</li>
<li>ベクタ(<code>Vec<T></code>)</li>
<li>ハッシュマップ(<code>HashMap<K, V></code>)</li>
</ul>
</li>
</ul>
<p>たとえば構造体なら</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">Person</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">age</span>: <span class="kt">u32</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">name</span>: <span class="nb">String</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">p1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Person</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">age</span>: <span class="mi">24</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">name</span>: <span class="s">"alice"</span><span class="p">.</span><span class="n">to_string</span><span class="p">(),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">};</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"p1 = </span><span class="si">{}</span><span class="s"> (</span><span class="si">{}</span><span class="s">)"</span><span class="p">,</span><span class="w"> </span><span class="n">p1</span><span class="p">.</span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">p1</span><span class="p">.</span><span class="n">age</span><span class="p">);</span><span class="w"> </span><span class="c1">//Output: p1 = alice (24)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>てな感じに書ける。</p>
<p>組み込みのデータ型との違いは,変数で示しているものが,値そのものではなく,値への参照(のようなもの<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>)という点である。</p>
<figure style='margin:0 auto;text-align:center;'><div class="lightmode"><a href="./variable-bindings1.svg"><img src="./variable-bindings1.png" srcset="./variable-bindings1.png 500w" sizes="(min-width:600px) 500px, 80vw" alt="" loading="lazy"></a></figure>
<p>今度は変数 <code>p1</code> の値を別の変数に代入してみよう。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">Person</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">age</span>: <span class="kt">u32</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">name</span>: <span class="nb">String</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">p1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Person</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">age</span>: <span class="mi">24</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">name</span>: <span class="s">"alice"</span><span class="p">.</span><span class="n">to_string</span><span class="p">(),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">};</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"p1 = </span><span class="si">{}</span><span class="s"> (</span><span class="si">{}</span><span class="s">)"</span><span class="p">,</span><span class="w"> </span><span class="n">p1</span><span class="p">.</span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">p1</span><span class="p">.</span><span class="n">age</span><span class="p">);</span><span class="w"> </span><span class="c1">//Output: p1 = alice (24)
</span></span></span><span class="line hl"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">p2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">p1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"p2 = </span><span class="si">{}</span><span class="s"> (</span><span class="si">{}</span><span class="s">)"</span><span class="p">,</span><span class="w"> </span><span class="n">p2</span><span class="p">.</span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">p2</span><span class="p">.</span><span class="n">age</span><span class="p">);</span><span class="w"> </span><span class="c1">//Output: p2 = alice (24)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>一見うまく言っているようだが,<code>println!</code> マクロ<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> の位置を変えると</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">Person</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">age</span>: <span class="kt">u32</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">name</span>: <span class="nb">String</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">p1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Person</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">age</span>: <span class="mi">24</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">name</span>: <span class="s">"alice"</span><span class="p">.</span><span class="n">to_string</span><span class="p">(),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">};</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">p2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">p1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"p1 = </span><span class="si">{}</span><span class="s"> (</span><span class="si">{}</span><span class="s">)"</span><span class="p">,</span><span class="w"> </span><span class="n">p1</span><span class="p">.</span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">p1</span><span class="p">.</span><span class="n">age</span><span class="p">);</span><span class="w"> </span><span class="c1">//Error: value borrowed here after move
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"p2 = </span><span class="si">{}</span><span class="s"> (</span><span class="si">{}</span><span class="s">)"</span><span class="p">,</span><span class="w"> </span><span class="n">p2</span><span class="p">.</span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">p2</span><span class="p">.</span><span class="n">age</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>コンパイルエラーになる。</p>
<p>これは</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">p2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">p1</span><span class="p">;</span><span class="w">
</span></span></span></code></pre></div><p>の部分で値がコピーされず,所有権のみ移動してしまうため。</p>
<figure style='margin:0 auto;text-align:center;'><div class="lightmode"><a href="./variable-bindings2.svg"><img src="./variable-bindings2.png" srcset="./variable-bindings2.png 500w" sizes="(min-width:600px) 500px, 80vw" alt="" loading="lazy"></a></figure>
<p>構造体やコレクションの各型の値はヒープ領域に置かれる。
ヒープ上の値に対して代入等を行うたびにコピーを行うのは高コストだし,かといって野放図に参照を増やすとヒープ管理が煩雑になってしまう。</p>
<p>そこで所有権を「移動」することでヒープ管理の最適化を行うわけだ。</p>
<h2>Copy/Clone Trait</h2>
<p>じゃあ,構造体やコレクションのコピーはできないのかというと,ちゃんと救済措置はある。</p>
<p><a href="https://www.rust-lang.org/" title="Rust Programming Language">Rust</a> の標準ライブラリには <code>Clone</code> および <code>Copy</code> トレイトが用意されていてこれらを実装することで値のコピーが可能になる<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>。</p>
<p>たとえば先程の <code>Person</code> 構造体に <code>Clone</code> トレイトを実装すると</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">Person</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">age</span>: <span class="kt">u32</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">name</span>: <span class="nb">String</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="w"></span><span class="k">impl</span><span class="w"> </span><span class="nb">Clone</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">Person</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="w"> </span><span class="k">fn</span> <span class="nf">clone</span><span class="p">(</span><span class="o">&</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-> <span class="nc">Self</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="w"> </span><span class="n">Person</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="w"> </span><span class="n">age</span>: <span class="nc">self</span><span class="p">.</span><span class="n">age</span><span class="p">,</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="w"> </span><span class="n">name</span>: <span class="nc">self</span><span class="p">.</span><span class="n">name</span><span class="p">.</span><span class="n">clone</span><span class="p">(),</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">p1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Person</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">age</span>: <span class="mi">24</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">name</span>: <span class="s">"alice"</span><span class="p">.</span><span class="n">to_string</span><span class="p">(),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">};</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">p2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">p1</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"p1 = </span><span class="si">{}</span><span class="s"> (</span><span class="si">{}</span><span class="s">)"</span><span class="p">,</span><span class="w"> </span><span class="n">p1</span><span class="p">.</span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">p1</span><span class="p">.</span><span class="n">age</span><span class="p">);</span><span class="w"> </span><span class="c1">//Output: p1 = alice (24)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"p2 = </span><span class="si">{}</span><span class="s"> (</span><span class="si">{}</span><span class="s">)"</span><span class="p">,</span><span class="w"> </span><span class="n">p2</span><span class="p">.</span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">p2</span><span class="p">.</span><span class="n">age</span><span class="p">);</span><span class="w"> </span><span class="c1">//Output: p2 = alice (24)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>のように <code>clone()</code> メソッドでコピーを生成できるようになる。
図にすると,こんな感じか。</p>
<figure style='margin:0 auto;text-align:center;'><div class="lightmode"><a href="./variable-bindings3.svg"><img src="./variable-bindings3.png" srcset="./variable-bindings3.png 500w" sizes="(min-width:600px) 500px, 80vw" alt="" loading="lazy"></a></figure>
<p>あるいは <code>derive</code> 構文<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> を使えば</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line hl"><span class="cl"><span class="cp">#[derive(Clone)]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">struct</span> <span class="nc">Person</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">age</span>: <span class="kt">u32</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">name</span>: <span class="nb">String</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">p1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Person</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">age</span>: <span class="mi">24</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">name</span>: <span class="s">"alice"</span><span class="p">.</span><span class="n">to_string</span><span class="p">(),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">};</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">p2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">p1</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"p1 = </span><span class="si">{}</span><span class="s"> (</span><span class="si">{}</span><span class="s">)"</span><span class="p">,</span><span class="w"> </span><span class="n">p1</span><span class="p">.</span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">p1</span><span class="p">.</span><span class="n">age</span><span class="p">);</span><span class="w"> </span><span class="c1">//Output: p1 = alice (24)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"p2 = </span><span class="si">{}</span><span class="s"> (</span><span class="si">{}</span><span class="s">)"</span><span class="p">,</span><span class="w"> </span><span class="n">p2</span><span class="p">.</span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">p2</span><span class="p">.</span><span class="n">age</span><span class="p">);</span><span class="w"> </span><span class="c1">//Output: p2 = alice (24)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>のようにコンパイラが自動的に <code>Clone</code> トレイトを実装してくれる。</p>
<p>実を言うと</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="cp">#[derive(Copy, Clone)]</span><span class="w">
</span></span></span></code></pre></div><p>とすれば代入時に値をコピーできるようになるのだが, <code>Person</code> 構造体ではコンパイルエラーになってしまい上手く行かなかった。
色々試してみたが,どうも <code>String</code> 等のコレクションを含む構造体の <code>Copy</code> トレイトは実装できないようだ<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup>。</p>
<p>属性にコレクション型を含まないのであれば</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line hl"><span class="cl"><span class="cp">#[derive(Copy, Clone)]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">struct</span> <span class="nc">Complex</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">real</span>: <span class="kt">f64</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">image</span>: <span class="kt">f64</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">c1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Complex</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">real</span>: <span class="mf">1.23</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">image</span>: <span class="mf">4.5</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">};</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">c2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">c1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"c1 = </span><span class="si">{}</span><span class="s"> + </span><span class="si">{}</span><span class="s">i"</span><span class="p">,</span><span class="w"> </span><span class="n">c1</span><span class="p">.</span><span class="n">real</span><span class="p">,</span><span class="w"> </span><span class="n">c1</span><span class="p">.</span><span class="n">image</span><span class="p">);</span><span class="w"> </span><span class="c1">//Output: c1 = 1.23 + 4.5i
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"c2 = </span><span class="si">{}</span><span class="s"> + </span><span class="si">{}</span><span class="s">i"</span><span class="p">,</span><span class="w"> </span><span class="n">c2</span><span class="p">.</span><span class="n">real</span><span class="p">,</span><span class="w"> </span><span class="n">c2</span><span class="p">.</span><span class="n">image</span><span class="p">);</span><span class="w"> </span><span class="c1">//Output: c2 = 1.23 + 4.5i
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>てな感じに簡単に <code>Copy</code> トレイトを実装できる。</p>
<p>ふむむー。</p>
<h2>ブックマーク</h2>
<ul>
<li><a href="https://dev.classmethod.jp/server-side/language/rust-copy-semantics-use-copy-trait/">RustのコピーセマンティクスをCopyトレイトを実装して確認する | Developers.IO</a></li>
</ul>
<h2>参考図書</h2>
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/4048930702?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/51YLqKD4N5L._SL160_.jpg" width="124" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/4048930702?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">プログラミング言語Rust 公式ガイド</a></dt>
<dd>Steve Klabnik (著), Carol Nichols (著), 尾崎 亮太 (翻訳)</dd>
<dd>KADOKAWA 2019-06-28 (Release 2019-06-28)</dd>
<dd>単行本</dd>
<dd>4048930702 (ASIN), 9784048930703 (EAN), 4048930702 (ISBN)</dd>
<dd>評価<abbr class="rating fa-sm" title="4"> <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="far fa-star"></i></abbr></dd>
</dl>
<p class="description"><a href="https://doc.rust-lang.org/book/">公式ドキュメント</a>の日本語版。索引がちゃんとしているので,紙の本を買っておいて手元に置いておくのが吉。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2020-02-24">2020-02-24</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- プログラミング言語Rust 公式ガイド -->
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>厳密には <a href="https://www.rust-lang.org/" title="Rust Programming Language">Rust</a> で<a href="https://text.baldanders.info/rust-lang/references-and-borrowing/" title="参照と借用">「参照」は別のものを指す</a>ので,ここではユルく「のようなもの」という感じでご容赦を。 <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
<li id="fn:2">
<p><code>println!</code> って関数じゃなくてマクロなんですよ,奥さん。 <a href="#fnref:2" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
<li id="fn:3">
<p>「トレイト(trait)」とは,ここでは C++ や Java で言うところの interface クラスのようなものだと思っておけばよい。トレイトに関しては多分その内ちゃんとした記事を書くと思う(笑) <a href="#fnref:3" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
<li id="fn:4">
<p><code>derive</code> はマクロに似た拡張構文の一種。詳細については割愛する。ていうか,これから勉強する(笑) <a href="#fnref:4" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
<li id="fn:5">
<p><code>derive</code> 構文を使った <code>Copy</code> トレイトの実装はあくまでも bitwise なもので,たとえ <code>String</code> 等で <code>Copy</code> トレイトを実装してもスタック上のポインタ値等がコピーされるだけなので意味がないそうな。 <a href="#fnref:5" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
</ol>
</div>