Rust入門
🦀🦀🦀
配列
code:rust
// スライス
Vec
code:rust
let mut vec = Vec::new();
vec.push("hello");
vec.push("world");
// スライス
println!("{:?}", &vec1..2); // 2 Tuple
code:rust
println!("{:?}", ()); // 空のタプル
let tuple = (1, "hello", 5.3);
println!("{}", tuple.0); // 1
println!("{}", tuple.1); // hello
println!("{}", tuple.2); // 5.3
let (n, s, f) = tuple;
println!("{}, {}, {}", n, s, f); // 1, hello, 5.3
HashMap
code:hashmap.rs
use std::collections::HashMap;
fn main() {
let mut h = HashMap::new();
h.insert("hoge", 1);
h.insert("piyo", 3);
h.insert("piyo", 4);
// []でキーに紐づく値を取得できる. キーが存在しないときはエラーが発生する.
// get()は[]とは異なり、キーが存在しなくてもエラーが発生しない
match h.get("piyo") { // 4
Some(n) => println!("{}", n),
None => println!("😫"),
}
}
HashSet
内部的にはHashMapを使用して実装されているようです
順序を維持したいときは、HashSetの代わりにBTreeSetを使う
code:hashset.rs
use std::collections::HashSet;
fn main() {
let mut s = HashSet::new();
s.insert("hoge");
s.insert("piyo");
s.insert("fuga");
s.insert("piyo");
println!("{}", s.len()); // 3
println!("{}", s.contains("hoge")); // true
println!("{}", s.contains("piyopiyo")); // false
}
Iterator
.iter()と.into_iter()の違いはmoveの有無. .into_iter()はmoveが発生するので、もとのコレクションは使用できなくなる
文字列
code:rust
let s = "Hello, world!"; // &'static str
let s = String::from(s); // String
タプル構造体
code:rust
struct Point(i32, i32);
fn main() {
let p = Point(1, 3);
println!("({}, {})", p.0, p.1); // (1, 3)
}
名前付き構造体
code:rust
struct Point {
x: i32,
y: i32,
}
fn main() {
let p = Point{ x: 1, y: 3 };
println!("({}, {})", p.x, p.y); // (1, 3)
let (x, y) = (3, 5);
let p = Point{ x, y };
println!("({}, {})", p.x, p.y); // (3, 5)
// デストラクチャリング
let Point { x, y } = p;
println!("({}, {})", x, y); // (3, 5)
}
enum
code:rust
enum Status {
OK,
Error(String),
}
fn main() {
let s = Status::Error(String::from("😑😑😑"));
match s { // Error: 😑😑😑
Status::OK => println!("OK😊"),
Status::Error(msg) => println!("Error: {}", msg),
}
}
match
code:rust
match 10 { // => piyo 10
1 => println!("hoge"),
n @ 10 => println!("piyo {}", n),
_ => println!("fuga"),
}
ループ
code:rust
let mut i = 0;
while i < 3 {
println!("{}", i); // 0, 1, 2
i += 1;
}
loop {
do_something();
if some_condition_met() {
break;
}
}
for n in 0..5 {
println!("{}", n); // 0, 1, 2, 3, 4
}
メソッド
code:methods.rs
struct Person {
name: String,
age: u32,
}
impl Person {
// 静的メソッド
fn new(name: String, age: u32) -> Self {
Self { name, age }
}
// 通常のメソッド
fn rename(&mut self, new_name: String) {
self.name = new_name;
}
}
fn main() {
let mut p = Person::new(String::from("hoge"), 30);
p.rename(String::from("piyo"));
println!("{:?}", p); // Person { name: "piyo", age: 30 }
}
Option
code:option.rs
fn second(vec: Vec<i32>) -> Option<i32> {
if vec.len() < 2 {
None
} else {
}
}
fn main() {
match second(vec!1, 2, 3) { // => 2 Some(n) => println!("{}", n),
None => println!("None"),
}
match second(vec!1) { // => None Some(n) => println!("{}", n),
None => println!("None"),
}
}
lambda
code:rust
// 引数なし
let f = || println!("Hello");
f();
// 引数あり
let add = |a: i32, b: i32| {
// ブロック
let result = a + b;
result
};
println!("{}", add(1, 2));
// closure
{
let message = "Hello world!";
let do_something = || println!("{}", message);
do_something();
}
ライフタイム
Copyトレイト
Copyトレイトを実装した型はスタック上に確保される
関数に渡す際は常にコピーされる
所有権について心配する必要はない
Cloneトレイト
.clone()でクローンできる
AsRefトレイト
ある型から別の型への参照を取得したいときに使う
例えば、AsRefを使うと、以下のように&strとStringの両方を受け取れる関数を定義できる
code:rust
fn decorate_text<T>(x: T) -> String
where
T: AsRef<str> + Display,
{
format!("**{}**", x)
}
fn main() {
println!("{}", decorate_text("Hello"));
println!("{}", decorate_text("world".to_string()));
}
From<T>/Into<T>トレイト
Cowトレイト
Rc
参照カウントを使用したスマートポインタ
ArcはRcのatomic版
Box
Boxトレイトとdynについて
Channel
std::sync::mpsc::channelで作成できる
参考