Cloneは用法容量を守って使いましょう。

# Cloneは用法容量を守って使いましょう。

## TL;DR

- Cloneは、メモリコピーのコストもあるが、リソースの保持者が分かりにくくなるので注意が必要
- 参照をうまく使うことでCloneを減らすことができる。
- Cloneは悪でもない。必要なら、簡単に書けるならCloneを使うことも考えるべき。
- Cloneする前提の形に持って行ってもいい。

# Clone、それは魔法の言葉

> Rustを使っているということは、ボローチェッカーとの闘いでもある

ボロー(借用)チェッカーというのは、Rust特有の所有権、借用という概念が正しく実装出来ているかをコンパイラが確認することである。
そしてそれが守られてないとコンパイラ様に、
- 「この変数もう使われたから使わないでね」
- 「この変数は可変で借りれないよ」

などと叱られるになる。
そして慣れないうちは、「何を言っているのだこいつは」とイラっとする。

そんなボローチェッカーへの最も簡単な答えが
`clone()`、もしくは`to_owned()`である。

「ほら`Clone`してやったよ。これで静かにしてろ。」

そういわんばかりに`clone`,`clone`,`clone`と唱えればキャンキャン吠える犬のごときコンパイラもさすがに沈黙してくれるだろう。


しかし、 ~~社会の理不尽で非合理に見えるルールとは違い、~~ コンパイラはしっかりと訳があってその警告を出している。
そのためRustの思想を理解し、自分のプログラムの構造を理解することで、コンパイラを第三の目とすることができるだろう。
所有権、参照はRustの思想の根幹の一つである。

そのためRustの有名なアンチパターンである`Clone`の多用を解消するために説明する。

# Q. そもそも`Clone`でなんで黙らせられるの？

## A 所有権が新しいリソースに対してあるから

Rustには所有権の概念がある。
簡単にいうと誰がそのリソース(文字列`String`や`Vec`、`File`などのメモリやコネクションなど)を扱う権限を持っているかという話だ。
Rustでは基本的に一つのリソースに対して一変数を対応させることでいろいろな問題を対処している。
例えば
- 複数のスレッドから同じ値に書き込めたらデータレースが起こる。
- ある変数が変わんないことを前提とするロジックに対して途中で変更が入る

などの問題をコンパイル時に抑制することでリソースの管理の明確化と実行時のチェックのコストを低減している。
また余計なデータの移動を防ぐことでの最適化もしてくれる。

ここで`clone`するとどうなるか。
`clone`するとリソースを新たに作り、その新しいリソースの所有権を得ることでその変数が、自分が所有権を持っていると証明することができる。そのため`clone`すると所有権関係のエラーがなくなる。


現実的な例で例えると、テレビを使いたい時に他の人がそのテレビを見たいと言ったらもう一つテレビを買ってくるようなものである。


# Q. それなら`Clone`で問題ないのでは？
## A.  問題がでる場合もある。

例えば変更したと思った物が反映されないという問題が起きることもある。

```rust

let mut a = "xxxx".to_string(); 
let mut b = a.clone();
b += "yyy";

assert_eq!("xxxxyyy", a); // error!

```

この程度の例なら簡単に思えるが、複雑になってくると見落とすこともあるのではないか？

それにクローンするということは大抵の場合deep copyすることが多い。そのため実行速度とメモリに余計なコストがかかることになる。

また見た目が悪いし、いちいち書くのが手間になってくるのではないか。

テレビの例だとある番組を見るためだけにテレビを買ってきて、見終わったらテレビを捨てるということである。


# Q. ではどうやって解消するの？
## A1. 基本的には借用を使う。

そもそもとして所有権自体を持っている必要な場合は少ない。
大抵の場合借用をして参照を渡せばいいだけのことが多いのである。

### 借用とは?

借用とは、所有権ではなく、参照する権利を渡すことである。

テレビの例だとすると所有権者はテレビを持っていれば良くて、
テレビを見る権利は渡してもいい。
同じ番組を見たい人がいるならテレビを買ってこなくても、横からのぞきこめばいいのである。

ただチャンネルを変える権利(リモコン)も渡せるが、リモコンを複数渡してもチャンネルがころころ切り替わるような状態では画面をみてはいられないだろう。
そのために可変参照は一つしかとれないようになっている。


### 借用を使おう

大抵cloneが必要になるのは
- 関数に入れるときに所有権を持っていることを要求される
- 参照として引数に渡されたものから所有権付きで返す必要がある


### 関数が所有権を要求する
まず一番の例だが、その関数が自分のものであるとき引数を参照にできないかを考える。

``` rust

// clone()でなくてto_owned()だがほとんど同じ
let x = "aaa".to_owned();

fn f1(x : String) {
    println!("hello {x}");
}

f1(x)

```


``` rust

//to_owned()が消えた。
let x = "aaa";

fn f2(x : &str) {
    println!("hello {x}");
}

f2(x);

```

それから参照で使ってから最後に所有権を手放すつもりで使えば、cloneする必要がなくなる。


```rust

fn g1(y: String){}
fn g2(y: &str){}

```

```rust
let y = "aaa".to_owned();
g1(y.clone());
g2(&y);
```

```rust

g2(&y);
g1(y);

```
ただこれはロジックとして許される限りである。

---

### 返り値が所有権を要求する

二つ目の例だが、本当に所有権付きで返す必要があるかを考える。
その返り値は参照で返せないか？
ただこれもロジックの意味論的に許す限りである、

```rust
#[derive(Debug)]
struct P1{
    name : String
}

fn make_p1(s : &str) -> P1{
    P1{ name : s.to_owned() }
}

let p = make_p1(x);
println!("{p:?}");

```

```rust

#[derive(Debug)]
struct P2<'a>{
    name: &'a str
}

fn make_p2(s : &str) -> P2 {
    P2{ name: s }
}

let p = make_p2(x);
println!("{p:?}");

```


### 借用を使うかどうか

```mermaid
sequenceDiagram
    participant f1
    participant f2
    participant f3
    f1->>+f2:引数a1
    f2->>+f3:引数a2
    f3->>-f2:返り値r2
    f2->>-f1:返り値r1
```

おおよそ関数を呼ぶということはこういったことになるはず。
引数から値を加工して新しく値を作って返すとき、
- 元の値はもう使わないならcloneせずとも消費(consume)して所有権が渡せる
- 元の値自体を書き換えていいなら可変参照を使う(返り値で返さず変更するだけにする)
- 元の値をそのまま使うならclone、またはそれに類する処理が必要

また参照で関数を渡していけば、必要になったときだけcloneするということもできる。

```rust
fn check(x : &str) -> Result<(),Error>{
    match x {
        "y" => Ok(()),
        err => Err(Error::CheckFail(err.to_owned()))
    }
}
```

慣れてくれば、どこで参照が使えてどこで所有権を渡し、どこでcloneするかが分かるようになってくる。
今のコンパイラはエラーが親切なのでそれを読むと代替解消できることが多い。
(ただそれでも分かりずらかったり、簡単には直せなかったりする。)

### Cow

ちなみに変更する直前まで参照として扱い、変更の必要があれば内部で`clone`(厳密には`to_owned`)するというCowというものもある。

```rust
const AAA : &'static str = "aaa";
let mut c : Cow<_> = AAA.into();//cowにする
let c_ref : &str = &c;// c.as_ref();でも同じ
assert_eq!(AAA.as_ptr(), c_ref.as_ptr());//cowにいれてもポインタの位置は同じ
c += "yyy";
println!("{c}");
assert_ne!(AAA.as_ptr(), c.as_ref().as_ptr());//cowに変更が入ると自分でcloneしてそこに変更する。
```


## A2. `Rc`,`Arc`を使う

Cloneが問題になるのはRustのCloneは基本的にdeep copyをしているから。
これをshallow copyにするために`Rc`,`Arc`を使う。
`Rc`(参照カウンタ)はリソースを共有しながら、所有権を持たせる手法である。
基本的には機能は同じで、同期的に使うなら`Rc`,非同期に使うなら`Arc`を使うことになる。
GCのある言語のObjectに近いものである。
これによってcloneのコストを下げることができる。

(ただ参照渡しと比べて参照カウンタの変更などのコストはある。)

```rust

let a : std::rc::Rc<str> = "xxx".into();
let b = a.clone();

assert_eq!(a.as_ptr(), b.as_ptr()); // cloneしても指しているポインタは同じ
```

# まとめ

- `Clone`は所有権の問題を解消するために使いがちだが、根本的になぜ`Clone`が必要か考えるべきである。
- 参照をうまく使えば`Clone`が減る。
- `Rc`,`Arc`などでshallow cloneするように変更するとコストが減る。


# 余談 `Clone`と`ToOwned`

`clone`は自分自身の型にリソースを複製する。
`to_owned`は自分の型とは違う型だが同じリソースを使うように複製する。

例えば`<&str>::to_owned()`は`String`型を返す。