Mozillaが開発中のシステム言語
色々尖ってる
公式のホームページいってinstallerとバイナリをダスンロード出来ますが、
$ curl -sSf https://static.rust-lang.org/rustup.sh | sh
でinstallが一番簡単
$ rustc main.rsでコンパイルできる。
fn main(){ println!("hello world") }
printlnは分かるけど後ろについている !は何?
答えはマクロ hello worldからマクロ
macro_rules! println { ($fmt:expr) => (print!(concat!($fmt, "\n"))); ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); }
こんな感じに展開される マクロで定義されたものは!マークがつく。 macro_rules!はマクロ定義の構文らしい
let x = 3; //再代入不可 let mut x = 3; //再代入できる
fn add(a:int, b:i32)->i32{ a + b }
struct Point { x: i32, y: i32, } enum Animal{ Cat, Dog, } //代数的データ型 enum Option<T> { Some(T), None, }
let x = Some("fuge"); match x { None => println!("None!"), Some("hoge") => println!("hoge"), Some("fuge") => println!("fuge"), // match! }
let sum = (0..101).fold(0, |sum, n| sum + n); println!("{}", sum);
trait Foo { fn method(&self); }
rustのトレイトは型クラスのように扱える。 実装を書くことでFooとして型制約を書ける。 (selfを引数を取るとmethodのように書けるのがpythonっぽい)
impl Foo for String { fn method(&self){println!("{}", *self)} } fn foo<T:Foo>(t:T){ t.method(); } foo("foo".to_string)//OK! foo(3) // error: the trait `Foo` is not implemented for the type `_`
特殊なtraitを実装する事で演算子のオーバーロードが使える
#[derive(Debug)] struct Point { x: i32, y: i32 } impl Add for Point { type Output = Point; fn add(self, other: Point) -> Point { Point {x: self.x + other.x, y: self.y + other.y} } } fn main() { let point = Point {x: 1, y: 0} + Point {x: 2, y: 3}; println!("{:?}", point); }
Rustのポインタにはlifetimeと所有権という概念があり、ヒープの解放などの処理はコンパイラが面倒を見てくれる。
//スタックへのポインタは返せない fn fuge()->&i32{// missing lifetime specifier let x = 3;//スタックに変数を積む。 &x; } fn main(){ { let hoge = Box::new("hoge"); // 文字列をヒープに割り当てる。 }//スコープの外に出ると解放する。 }
Rustでは参照を関数に渡したり変数に代入すると所有権の移動が起こる。
fn boxed_int(i:Box<i32>){ println!("{}", i); }//ここでiは解放される fn main(){ let x = Box::new(3); boxed_int(x); println!("{}", x) // use of moved value: `x` }
boxed_int関数に所有権が移ってしまったので、使用できない。
&変数 で借用が使える
fn borrow_int(i:&i32){ println!("{}",i); }//iは解放されない fn main(){ let x = Box::new(3); borrow_int(&x); println!("{}", x); }
貨しているだけなので borrow_intが終了した後でも使用できる。
fn main() { let mut x = Vec::new(); x.push("hello"); let y = &mut x[0]; //先頭の要素への参照 x.push("world"); // pushする事でyが無効なメモリを参照してしまう可能性がある。 println!("{:?}",y); }
コンパイルすると
error: cannot borrow `x` as mutable more than once at a time
ちゃんとコンパイルエラーになる
値をコピーするとコンパイルが通る
fn main() { let mut x = Vec::new(); x.push("hello"); let y = &mut x[0].clone();//クローンしている。 x.push("world"); println!("{:?}",y); }
理解できるまで時間がかかりそう。