RUST

メモ帳

todo:

目次

initialize

gitも一緒にできる

cargo init

main.rs

ここが始まり

fn main() {}

stdout

println!(data);
// or
print!(data);

println!("{}", data_not_str);

変数と定数

Rustはletで変数定義を行う

ただ、何も考えないと定数として扱われる

let i = 0;
i = 1; // error

let mutとすれば変数になる

let mut i = 0;
i = 1; // ok

数値

int

未指定でi32

unsigned int

float

未指定(0.0等)でf64

その他

usize

インデックスを扱うときに使う

数値への型変換

// 数値から数値
// 一番かんたんなものは
// 値または変数 as 型名
let a: i32 = -10;
let b: u64 = a as u64;
assert_eq!(b, 0); // こういうことが起きる
// float to intはこうするしかない

// 絶対安全な型変換は
// 型名::from(値);
let c: i64 = i64::from(a);

// 安全でない型変換は
// 型名::try_into(値); (返り値: Result<...>)
let d: Result<u32, std::num::TryFromIntError> = u32::try_from(a);

// 文字列(&str, String)から数値 (返り値: Result<...>)
let e = "10";
let f = a.parse();

文字列

// 何も指定しないと&'static str型となる
// 基本は&str型としておく
let a: &str = "aaa";

// Stringは以下の通り
let b: String = String::from("bbb");
let c: String = String::from(a);

// &strのコピーはCのchar *と同じくかんたんにはできない
// Stringのコピーは以下の通り
let d: String = b.clone();

// 文字列の結合は+を使うだけ
// ただし、一番最初の型はString, それ以外は&strまたは&String
let e: String = d + &c + &b + a;

// Stringでは二度以上参照すると所有権の問題でエラーが出る
let f: String = e + &e; // error
// clone()でコピーする必要がある
let g: String = e.clone() + &e.clone();

文字列への型変換

// String -> &str
let a: String = String::from("a");
let b: &str = &a;
// 数値 -> 文字列
let c: i32 = 0;
let d: String = c.to_string();

配列とVec

配列

長さの変更ができない

// 配列定義
// [初期値;長さ]
let mut arr = [0;10];

// [...値]
let arr2 = [1, 2, 3, 4, 5];

Vec

可変長配列

// Vec定義
// vec![]
let mut vec1: Vec<i32> = vec![];
// vec![初期値;長さ]
let mut vec2: Vec<i32> = vec![0;10];
// vec![...要素]
let mut vec3: Vec<i32> = vec![0,1,2,3,4];

// push()で末尾に追加できる (mut必要)
vec1.push(10);
// pop()で末尾を取り出せる (mut必要)
let a: Option<i32> = vec1.pop();

配列Vec共通

// 取り出すのはいつもどおり
assert_eq!(arr[0], 0);
// Option<...>でも取り出せる(こちらのほうが安全)
let b: Option<i32> = arr.get(0);

// 長さはlen()
let size: uzise = arr.len();

// sortでソートができる (mut必要) 最悪計算量がO(n * log(n))
arr.sort();

Result

結果と返り値を持つもの, Ok() or Err()

is_ok()is_err()で問題の有無を確認でき、ok()err()で内容をOption<...>で取得できる

Option

値を持たないかもしれないもの, Some() or None

配列.get(インデックス)で配列外を参照したときなどに出てくる

条件分岐

if

条件式では()がいらない

if

let a: i32 = 0;
if a > 0 {
  println!("a is positive");
} else if a < 0 {
  println!("a is negative")
} else {
  println!("a is zero")
}

ifは文ではなく式のため、以下のようなことができる


let a = 0;
// ifの結果をbに代入する
// この場合はelseが必須
let b = if a > 0 {
  "positive" // ここに;がないのは、これを返り値とするため。
} else if a < 0 {
  "negative"
} else {
  "zero"
}; // ここに;が必要
println!("{}", b);

loop

無限ループ

loop {
  println!("!");
}
println!("?"); // ここには到達しない

while

条件を満たす限り繰り返す

条件式には()不要

let mut i = 0;
while i < 10 {
  i += 1;
}
assert_eq!(i, 10);

for

範囲内で繰り返す

let a: Vec<i32> = vec![0, 1, 2];
for x in a.iter() {
//       ^^^^^^^^ forで回すには配列.iter()とする
  println!("{}", x);
}
println!("{:?}", a);

for x in a {
//       ^ 配列.iter()としないと
  println!("{}", x);
}
println!("{:?}", a); // error: ここで利用できない

if_let

以下のようなことができる

let a: Vec<i32> = vec![0, 1, 2];
let b: Option<&i32> = a.get(3);
if let Some(c: &i32) = b {
  println!("{}", c);
} else {
  println!("None");
}

while_let

if_letと同じ使い方

関数

fnで始める

どの場所に書いても構わない(利用よりも上に宣言を書く必要がない)

fn main() {
  test();
}

fn test() {
  println!("hello");
}

macro

println!とかvec!とかの!で終わるやつ

let mut vec1 = vec![0;5];
//             ^^^^ here
for a in vec1 {
  println!("{}", a);
//^^^^^^^^ here
}

使用

マクロ名!(変数など)またはマクロ名![変数など]またはマクロ名!{変数など}でできる

違いはない

// 全部意味は同じ
let mut vec1 = vec!(0;10);
let mut vec2 = vec![0;10];
let mut vec3 = vec!{0;10};

作成

macro_rules!から始まる

macro_rules! test {
  // 変数が何もない場合
  () => {
    // マクロ内でマクロを使うこともできる
    println!("test");
  };
  // 変数を用いる場合
  // !TODO
}