rust

自己参照構造体は作ることが出来ない

Qiitaからのメモ 【Rust】構造体に自身のフィールドの参照の配列を持たせる方法 - Qiita struct Bullet<'a>(&'a Texture); struct Enemy<'a> { bullet_texture: Texture, bullets: Vec<Bullet<'a>> } impl<'a> Enemy<'a> { fn new(bullet_texture: Texture) -> Self { E</bullet<'a>…

強参照Rc<T> と弱参照Weak<T>

std::rc::Rc<T> 概要 動的な参照を実現。&演算子による参照がコンパイル時にされるのに対して、Rc<T>は実行時に参照を確保する。 これによってライフタイムを除去することができる。 ライフタイムの除去 参照による共有 借用チェッカーを通すために、ライフタイム</t></t>…

std::rc::Rc<T> と std::cell::RefCell<T>

Rc::borrow_mut の問題 let file = File::open("text.txt")?; let mut bufreader = BufReader::new(&file); let shared_reader = Rc::new(bufreader); // NG let _ = *shared_reader.borrow_mut().read_line(&mut line)?; /* error[E0599]: no method named …

循環参照 - Rc<T>とRefCell<T>

循環参照はメモリーをリークする Rustのメモリ安全保障において、メモリーリークを発生させることはとてつもなく難しい。 Preventing memory leaks entirely is not one of Rust's guarantees in the same way that disallowing data race at compile time i…

スマートポインタ Rc<T> - 参照カウンタ

Rc<T>, the Reference Counted Smart Pointer 所有権は多くの場合において明白である。つまり「1変数は、1つの値の所有する 」。 しかしながら 一つの値が複数の所有者を持つ ケースが存在する。 例として、グラフ構造がある。 グラフは、複数の辺が同一のノ</t>…

ジェネリクスとトレイトオブジェクトの破壊的変更への対処

動機 ジェネリクスとトレイトオブジェクトの抱える問題 壮大たる破壊的変更につながる。 例 Fileインスタンスを持つStreamをジェネリクスに変更する struct Stream { reader: std::fs::File, } impl Stream { fn new(reader: std::fs::File) { Stream { read…

関数パラメーターにおける参照外し

関数パラメーターにおいても参照外しを行うことができる 例1 クロージャー map関数 let result = [1,2,3,4,5].iter().map(|&&x| x % 2 == 0).collect(); &&x : 参照参照外しをおこなっている 例2 関数の定義 参照外ししない場合 fn print_type_name<T>(_val: T)</t>…

Cargoプロジェクト Examplesの追加

Cargoで作ったライブラリプロジェクトにExamplesを追加することができる。 xion.io // examples/hello.rs fn main() { println!("Hello from an example!"); } $ cargo run --example hello $ cargo run --example hello2 -- Alice

トレイトオブジェクトの保持とライフタイム

トレイトオブジェクトとライフタイム トレイトオブジェクトを保持する場合は、ライフタイムが必要となる時がある。 ジェネリクス型パラメーター 参照型 トレイトオブジェクト x ジェンリクス型パラメーター struct Zoo { animals: Vec<Box<dyn Animal>>, // trait Animal { .</box<dyn>…

トレイト - 共通の振る舞いを定義する

https://doc.rust-lang.org/book/ch10-02-traits.html トレイト: 共通の振る舞いの定義 概要 トレイトを使って共通の振る舞いを定義 トレイトのデフォルト実装 トレイトをパラメーターに指定できる impl Trait トレイト境界 impl Traitのシンタックスシュガ…

トレイトの選択 完全限定構文 (Fully Qualified Syntax)

Fully Qualified Syntax Fully Qualified Syntax for Disambiguation: Calling Methods with the Same Name https://doc.rust-lang.org/book/ch19-03-advanced-traits.html fully qualified syntax (完全限定構文?) <Type as Trait>::function(receiver_if_method, next_arg</type>…

Iterator / IntoIterator / FromIterator

trait Iterator pub trait Iterator { type Item; fn next(&mut self) -> Option<Self::Item>; 実装している主要な型 std::slice::Iter<'a, T> Iterator派生型 Map Filter String.bytes Note: Vec<T>や配列[T]はIteratorではない。 これらがfor文で使えるのは、暗黙的にInto</t></self::item>…

クロージャー

概要 Rustのラムダ式はクロージャーと呼ぶ 関数ポインタ(fn)は、外部環境変数を含めることができない 関数ポインタもクロージャートレイトを実装している クロージャーの種類 (キャプチャー方法が異なる) FnOnce<Args>: selfメソッド, キャプチャー変数を消費する</args>…

スマートポインタの役割

Rustは関数ローカルの変数を参照として返すことができない impl Reader { fn new(path: impl AsRef<std::path::Path>) -> Reader { let file = std::fs::File::open(path).unwrap(); Reader { file: file, } } fn read_bytes(&mut self, len: usize) -> &[u8] { let mut bytes</std::path::path>…

トレイト まとめ

Self 将来実装される型を表す。 pub trait FromStr { type Err; fn from_str(s: &str) -> Result<Self, Self::Err>; impl FromStr for Haskellで言うところの型変数 a class Eq a where Eq: 型クラス a: 型変数, 具体型である必要がある。(型コンストラクタはNG) 関連型 type </self,>…

Borrow<Borrowed: ?Sized>トレイトとToOwnedトレイト

Stringの借用は、&strとして、&strの所有は、Stringとして表すことが出来る。 Rustでは、こういった関係をBorrow<Borrowed: ?Sized>とToOwnedトレイトを使って表すことが出来る。 Note: 参照 - ある所有された値への借用を表す型。コピーセマンティックである。 trait Borrow<Borrowed: ?Sized> </borrowed:></borrowed:>…

forループ文

TL;DR for文で回すには、以下のトレイトのどれかを実装する必要がある。 Iterator IntoIterator 配列はforループで回せない 配列は、どちらも実装していないため、forループ文で直接回せない。 let arr = [1,2,3,4,5]; // NG for i in arr { dbg!(i); } /* e…

配列型

配列型 サイズ固定配列。[T; N]で表す。 生成には2つの構文がある。 [x, y, z] [x; N]: 値xはCopy実装型でなければならない 配列は以下のトレイトを実装する。(ただしTも同様に実装されている必要がある) Copy Clone Debug IntoIterator: &[T; N]もしくは&m…

Iterator::findクロージャーに&&を渡さなければならない理由

https://stackoverflow.com/questions/43828013/why-is-being-used-in-closure-arguments let a = [1, 2, 3]; assert_eq!(a.iter().find(|&&x| x == 2), Some(&2)); assert_eq!(a.iter().find(|&&x| x == 5), None); 回答 aは[i32;3]型 [i32;3]型はiterメソ…

refキーワード

ref キーワード 参照として値を受け取ることが出来る let ref num = 5; // &i32 パターンマッチ内でも使用することが出来る let mut triple = (1, 2, 3); match triple { (1, ref mut second, 3) => *second *= 2, _ => panic!(), } dbg!(triple); // (1, 4,…

match式による構造破壊マッチング

match式による構造破壊マッチング match式のパターンマッチ内において、値を構造破壊することが出来る。 Destructuring Tuples タプル値を構造破壊してパターンマッチ let triple = (0, -2, 3); match triple { (0, y, z) => plintln!("First is `0`, `y` is…

型の種類とプリミティブデータ型

型の種類 T: 通常型 &T: 参照型 - ある所有された値への借用を表す型 [T; N] : 配列型 [T] : スライス型 *const T : ポインタ型 (T, U, V) : タプル型 fn(T) -> V : 関数型 プリミティブデータ型 bool char 一つのユニコードスカラー値 (4バイト表現) let x …

型 作成と実装

型(Type)の作成と実装 Rustは型(Type)の作成と実装が分かれる。 (最近はトレイトも実はサイズを持たない型(Type)と言えるのではないかと思うようになった) 型の作成は、struct, enumを使い、実装は impl を使う。 型の作成 struct enum Struct struct Point…

参照型とポインタ型

参照型とポインタ型 参照型 &T / &mut T - ある所有された値への借用を表す型 ポインタ型 *const T / *mut T - nullを表すことができる ポインタ型を使うメリットとデメリット Rustではポインタ型は、値がnullの可能性がある。 したがって扱う場合は、unsafe…

Iterator::collect()

Iterator::collect() fn collect<B>(self) -> B where B: FromIterator<Self::Item>, IteratorをCollectionに変換する。 collect()で変換できるCollectionはFromIterator<Self::Item>トレイトが実装されている必要がある。 Trait std::iter::FromIterator pub trait FromIterator<A> { fn f</a></self::item></self::item></b>…

関数ポインタとクロージャー

関数ポインタ fn do_twice(f: fn(i32) -> i32, arg: i32) -> { f(arg) + f(arg) } // add_one: fn(i32) -> i32 do_twice(add_one, 1); fn: 関数ポインタを表す 関数の引数にわたすことが出来る 3つのクロージャートレイト(Fn, FnMut, FnOnece)を実装している…

Cargo 開発コマンドチートシート

プロジェクトの生成 cargo new プロジェクト名 ./cargo/binディレクトリへのインストール cargo install -path . --path .: カレントディレクトリ配下のCargoプロジェクトをインストールする tomlの編集 cargo-editをインストールする必要がある。 外部クレ…

Result型 のアンラップとエラーの伝搬

Result<T, E>型の特徴 Rustは例外処理が存在しない代わりに、Result型でそれを実現する。 値のアンラップ エラーの伝搬 値のアンラップ unwrap: Err時、panic!を引き起こす unwrap_or: Err時、デフォルト値を返す unwrap_or_else: Err時、デフォルト値を生成する関</t,>…

Result map処理

Resultに用意されているmap処理 map: Okの型を変換する map_err: Errの型を変換する map_or: 値をアンラップする。デフォルト値を渡せる map_or_else: 値をアンラップする。デフォルト値の評価を遅延評価する map(成功時のmap処理) Result<T, E> から Result<U, E>に変換</u,></t,>…

標準入力から文字列を受け取る

<C-c>が入力されるまで受け付ける fn main() { // 標準入力へのハンドルを生成 (各ハンドルはバッファーを共有される) let stdin = std::io::stdin(); // lockすることでバッファーを専有する let stdin = stdin.lock(); // <C-c>が入力されるまで受け付ける for line </c-c></c-c>…