rust: Rustがんばろう 15日目
はじめに
まだまだトレイト。
「クレート」と「トレイト」の文字が似ているのも混乱している原因かもしれない(そうか?)。
trait が日本語版で「トレート」にならなかったのは発音もそうだが字面が近く鳴りすぎないためという配慮があったのかもしれない。
10.2章
クレートやモジュールなどの関係
クレートはコンパイルする単位。
たぶん “libXXX.a” や “libXXX.so” のようなライブラリ(Rustなので拡張子は違うだろうが)や ELF な実行ファイルのような
ひとまとまりにして意味があるような単位なのだろう。
モジュールはクレートの内側にあるもので、ソフトウェアの構造のために使う。
バイナリクレートとライブラリクレートがある。
バイナリクレートはいくつあってもよい。
ライブラリクレートは最大でも 1つまで。なくてもよい。
このくらいにしておこう。
引数タイプ
(item: &impl Summary) みたいな書き方で特定のトレイトを持ったインスタンスを参照できる。
参照したらそのトレイト関数?も呼び出しができる。
&impl Summary は引数や戻り値でしか使えないようで、let item: &impl Summary はエラーになった。
error[E0562]: `impl Trait` is not allowed in the type of variable bindings
--> src/main.rs:19:20
|
19 | let mut item: &impl Summary = &tweet;
| ^^^^^^^^^^^^
|
= note: `impl Trait` is only allowed in arguments and return types of functions and methods
= note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
vscode で補完に任せると &dyn が出てきた。
採用すると使えた。
let mut item: &dyn Summary = &tweet;
println!("tweet summary: {}", item.summarize());
item = &dummy;
println!("dummy summary: {}", item.summarize());
この引数の書き方は fn notify<T: Summary>(item: &T) の省略というかシンタックスシュガーだそうだ。
最近の言語ってシンタックスシュガー好きよねぇ。
C言語だと -> くらいかな? ポインタと配列を似たように扱えるのもその範疇に入るみたいだ。&a[0] とか書くの面倒だしな。
引数それぞれに &impl Summary する場合と trait bound のまま書いたときの違いは、
前者だと Tweet と NewsArticle の参照を引数にできるが、後者は Tweet 同士か NewsArticle 同士じゃないとエラーになった。
trait Summary という意味で同じ型ではなく、具体的な型として同じというわけか。
トレイト境界
“trait bound” は “トレイト境界” なのだが、
なんで「境界」なんだろう?
いや、元の “bound” から確認していくべきだ。
限界、境界、範囲、のような意味合いだが、言葉の成り立ちなどを見ていると縛る意味合いを持っている。
お前はここまでしかさせない、みたいな意味での境界のようだ。
ChatGPT 的には「このトレイトを実装していないといけませんよ」という「トレイト制約」だそうだ。
制約の方が私には受け入れやすいかな。
ここは日本語訳もあることだし “trait bound” で覚えておこう。
心の中ではトレイト制約だ。
where句
いきなり where 句って言われても。。。
このドキュメントは検索ができるのだが “where” と打ち込んでも出てこなかった。
where を使うとシグネイチャの先頭から戻り値までは普通のジェネリックな関数と同じ形に見える。
中でトレイトの関数を呼び出すので where でトレイトを指定しないとエラーになる。
こういう where で書き換えるのはシンタックスシュガーとは呼ばないのだろうか。
簡易表記、くらいの意味だと思っているのだけど、where を使っても簡易にはならないから違うとか?
シンタックスシュガーがあると、同じことを個人の好みで書くことになるので、 あれだ、覚えるのが面倒、ということだ。
&impl Trait だけでは <T: Trait> と同じことはできないことはあるが、
where 句は見やすくするかどうかだけなので、where 句の書き方だけ覚えておく?
でも引数が 1つだったら &impl Trait で書くことが多いだろうし・・・。
ツールにがんばってもらうということで、覚えるのは 1つにできるかもしれんな。
冗長だったらツールが指摘してくれることに期待しよう。
戻り値の impl Trail
戻り値も + は使えるのか?
このサンプルが Tweet を返すやつだったので、Tweet に Display トレイトを追加?したら使えた。
returns_summarizable() の中身は変更せずに済んだ。
impl Display for Tweet {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
todo!()
}
}
pub fn returns_summarizable() -> impl Summary + Display {
+ じゃなくてコンマで並べても良かったんじゃないのかという気がしたが、
コンマだとそれぞれに impl を書かないと気持ちが悪いか。
ならば足し算している方が感覚的にもわかりやすい。C# の delegate もそうだったっけ?
おわりに
春先なのに調子に乗って窓を開けて作業していたのだが、非常に調子が悪くなった。
花粉のやろう。。。