リスト : トレイト Add の定義 pub trait Add<RHS = Self> { type Output; fn add(self, rhs: RHS) -> Self::Output; }
リスト : 演算子の多重定義 use std::ops::Add; #[derive(Debug, Copy, Clone)] struct Point { x: f64, y: f64 } #[derive(Debug, Copy, Clone)] struct Point3d { x: f64, y: f64, z: f64 } impl Point { fn new(x0: f64, y0: f64) -> Point { Point { x: x0, y: y0 } } } impl Point3d { fn new(x0: f64, y0: f64, z0: f64) -> Point3d { Point3d { x: x0, y: y0, z: z0 } } } // 左辺と右辺でデータ型が同じ場合 impl Add for Point { type Output = Point; fn add(self, other: Point) -> Point { Point { x: self.x + other.x, y: self.y + other.y } } } impl Add for Point3d { type Output = Point3d; fn add(self, other: Point3d) -> Point3d { Point3d { x: self.x + other.x, y: self.y + other.y, z: self.z + other.z } } } // 右辺と左辺でデータ型が違う場合 impl Add<Point3d> for Point { type Output = Point3d; fn add(self, other: Point3d) -> Point3d { Point3d { x: self.x + other.x, y: self.y + other.y, z: other.z } } } impl Add<Point> for Point3d { type Output = Point3d; fn add(self, other: Point) -> Point3d { Point3d { x: self.x + other.x, y: self.y + other.y, z: self.z } } } fn main() { let p1 = Point::new(1.0, 1.0); let p2 = Point::new(2.0, 2.0); let p3 = Point3d::new(10.0, 10.0, 10.0); let p4 = Point3d::new(20.0, 20.0, 20.0); println!("{:?}", p1 + p2); println!("{:?}", p3 + p4); println!("{:?}", p1 + p3); println!("{:?}", p4 + p2); }
Point { x: 3, y: 3 } Point3d { x: 30, y: 30, z: 30 } Point3d { x: 11, y: 11, z: 10 } Point3d { x: 22, y: 22, z: 20 }
リスト : サイズ不定型の簡単な使用例 struct Foo<T: ?Sized> { buff: T // 大きさが異なる配列でも格納できる } fn main() { let a = [1,2,3]; let b = [1,2,3,4,5,6]; let c = Foo { buff: a }; let d = Foo { buff: b }; let e = Foo { buff: [1,2,3,4,5,6,7,8,9]}; println!("{:?}", c.buff); println!("{:?}", d.buff); println!("{:?}", e.buff); }
[1, 2, 3] [1, 2, 3, 4, 5, 6] [1, 2, 3, 4, 5, 6, 7, 8, 9]
リスト : トレイト Deref の定義 pub trait Deref { type Target: ?Sized; fn deref(&self) -> &Self::Target; }
リスト : トレイト Deref の簡単な使用例 use std::ops::Deref; struct Foo<T: ?Sized> { buff: T } impl<T> Deref for Foo<T> { type Target = T; fn deref(&self) -> &T { &self.buff } } struct Bar { num: i32 } impl Deref for Bar { type Target = i32; fn deref(&self) -> &i32 { &self.num } } fn main() { let a = Foo { buff: [1,2,3] }; let b = Foo { buff: [4,5,6,7,8,9] }; let c = Bar { num: 123 }; let d = Bar { num: 456 }; println!("{:?}", *a); println!("{:?}", *b); println!("{:?}", *c); println!("{:?}", *d); }
[1, 2, 3] [4, 5, 6, 7, 8, 9] 123 456
リスト : トレイト DerefMut pub trait DerefMut: Deref { fn deref_mut(&mut self) -> &mut Self::Target; }
リスト : DerefMut の簡単な使用例 use std::ops::{Deref, DerefMut}; struct Bar { num: i32 } impl Deref for Bar { type Target = i32; fn deref(&self) -> &i32 { &self.num } } impl DerefMut for Bar { fn deref_mut(&mut self) -> &mut i32 { &mut self.num } } fn main() { let mut c = Bar { num: 123 }; let d = Bar { num: 456 }; println!("{:?}", *c); println!("{:?}", *d); *c = 789; println!("{:?}", *c); }
123 456 789
リスト : deref の型強制 use std::ops::{Deref, DerefMut}; struct Bar { num: i32 } impl Deref for Bar { type Target = i32; fn deref(&self) -> &i32 { &self.num } } impl DerefMut for Bar { fn deref_mut(&mut self) -> &mut i32 { &mut self.num } } fn bar(x: &i32) { println!("{}", x); } fn main() { let mut c = Bar { num: 123 }; let d = Bar { num: 456 }; println!("{:?}", *c); println!("{:?}", *d); *c = 789; println!("{:?}", *c); bar(&c); bar(&d); let e = Box::new(1000); bar(&e); let f = Box::new(Bar { num: 2000 }); bar(&f); }
123 456 789 789 456 1000 2000
リスト : メソッド呼び出しの型強制 use std::ops::Deref; struct Foo { num: i32 } impl Foo { fn foo(&self) { println!("{}", self.num) } } struct Bar { content: Foo } impl Deref for Bar { type Target = Foo; fn deref(&self) -> &Foo { &self.content } } fn main() { let a = Box::new(Foo { num: 123 }); let b = Bar { content: Foo { num: 456 } }; let c = Box::new(Bar { content: Foo { num: 789 } }); a.foo(); b.foo(); c.foo(); }
123 456 789
リスト : Rc<T> の簡単な使用例 (1) use std::rc::Rc; #[derive(Clone)] struct Foo { num: i32 } impl Drop for Foo { fn drop(&mut self) { println!("Drop foo {}", self.num); } } fn main() { let a = Rc::new(Foo { num: 123 }); println!("{}", Rc::strong_count(&a)); let x = Box::new(Foo { num: 456 }); println!("{}", x.num); { let b = a.clone(); println!("{}", Rc::strong_count(&a)); println!("{}", Rc::strong_count(&b)); let c = &a; println!("{}", Rc::strong_count(&a)); println!("{}", Rc::strong_count(c)); let y = x.clone(); println!("{}", y.num); } println!("{}", Rc::strong_count(&a)); }
1 456 2 2 2 2 456 Drop foo 456 1 Drop foo 456 Drop foo 123
リスト : Rc<T> の簡単な使用例 (2) use std::rc::Rc; #[derive(Debug)] struct Foo { num: i32 } fn main() { let a = Box::new(Foo { num: 123 }); let b = *a; // move // println!("{}", a.num); コンパイルエラー println!("{}", b.num); let c = Rc::new(Foo { num: 456 }); // let x = *c; Rc の場合は単純に move することはできない { let d = c.clone(); // 参照カウンタが 1 よりも多いと Err match Rc::try_unwrap(d) { Ok(x) => println!("{}", x.num), Err(x) => println!("error {:?}", x) } } // 参照カウンタが 1 ならば Ok match Rc::try_unwrap(c) { Ok(x) => println!("{}", x.num), Err(x) => println!("error {:?}", x) } }
123 error Foo { num: 456 } 456
fn try_unwrap(this: Rc<T>) -> Result<T, Rc<T>>
リスト : 簡単な連結リスト (Rc 版) use std::rc::Rc; #[derive(Debug)] enum List { Nil, Cons(i32, Rc<List>) } use List::*; impl List { fn new() -> Rc<List> { Rc::new(Nil) } fn cons(x: i32, xs: &Rc<List>) -> Rc<List> { Rc::new(Cons(x, xs.clone())) } } impl Drop for List { fn drop(&mut self) { match *self { Nil => println!("drop Nil"), Cons(x, _) => println!("drop {}", x) } } } fn main() { let a = List::new(); println!("{:?}", a); { let b = List::cons(1, &a); println!("{:?}", a); println!("{:?}", b); println!("{}", Rc::strong_count(&a)); println!("{}", Rc::strong_count(&b)); { let c = List::cons(2, &b); println!("{:?}", a); println!("{:?}", b); println!("{:?}", c); println!("{}", Rc::strong_count(&a)); println!("{}", Rc::strong_count(&b)); println!("{}", Rc::strong_count(&c)); } println!("{}", Rc::strong_count(&a)); println!("{}", Rc::strong_count(&b)); } println!("{}", Rc::strong_count(&a)); }
Nil Nil Cons(1, Nil) 2 1 Nil Cons(1, Nil) Cons(2, Cons(1, Nil)) 2 2 1 drop 2 2 1 drop 1 1 drop Nil
リスト : Cell の簡単な使用例 use std::cell::Cell; struct Foo { x: i32, y: Cell<i32> } fn main() { let a = Cell::new(123); println!("{:?}", a); println!("{}", a.get()); a.set(456); println!("{:?}", a); println!("{}", a.get()); let b = Foo { x: 789, y: Cell::new(999) }; println!("{}. {:?}", b.x, b.y); b.y.set(1000); println!("{}, {:?}", b.x, b.y); let c = Box::new(Cell::new(1.234)); println!("{}", c.get()); c.set(5.678); println!("{}", c.get()); }
Cell { value: 123 } 123 Cell { value: 456 } 456 789, Cell { value: 999 } 789, Cell { value: 1000 } 1.234 5.678
リスト : RefCell の簡単な使用例 use std::cell::RefCell; #[derive(Debug)] struct Foo { x: i32, } impl Drop for Foo { fn drop(&mut self) { println!("drop foo {}", self.x); } } #[derive(Debug)] struct Bar { foo: RefCell<Foo> } fn main() { let a = RefCell::new(123); println!("{:?}", a); { println!("{}", *a.borrow()); // immutable な参照 } { let mut ref_a = a.borrow_mut(); // mutable な参照 *ref_a = 456; // println!("{}", *a.borrow()); immutable な参照を借りるとパニック } println!("{}", *a.borrow()); //immutable な参照 let b = Bar { foo: RefCell::new(Foo { x: 123 })}; println!("{:?}", b); { println!("{:?}", *b.foo.borrow()); // immutable な参照 } { let mut ref_b = b.foo.borrow_mut(); // mutable な参照 *ref_b = Foo { x: 456 }; // Foo { x: 123 } は廃棄される } println!("{:?}", b); let c = Box::new(RefCell::new(Foo { x: 789 })); println!("{:?}", c); { println!("{}", c.borrow().x); // フィールド x の値を参照する c.borrow_mut().x = 999; // フィールド x の値を書き換える println!("{:?}", c); } { let mut ref_c = c.borrow_mut(); // mutable な参照 *ref_c = Foo { x: 1000 }; // Foo { x: 999 } は廃棄される } let d = c.into_inner(); // メソッド into_inner() は中身のデータを move する // println!("{:?}", c); コンパイルエラーになる println!("{:?}", d); }
RefCell { value: 123 } 123 456 Bar { foo: RefCell { value: Foo { x: 123 } } } Foo { x: 123 } drop foo 123 Bar { foo: RefCell { value: Foo { x: 456 } } } RefCell { value: Foo { x: 789 } } 789 RefCell { value: Foo { x: 999 } } drop foo 999 Foo { x: 1000 } drop foo 1000 drop foo 456
リスト : Cell の簡単な使用例 (その2) use std::cell::Cell; struct Foo { num: Cell<i32> } impl Foo { fn new(x: i32) -> Foo { Foo { num: Cell::new(x) } } fn get_num(&self) -> i32 { self.num.get() } fn set_num(&self, x: i32) { // immutable な参照でも更新できる self.num.set(x) } } fn main() { let a = Foo::new(100); let b = &a; let c = &a; println!("{}", a.get_num()); println!("{}", b.get_num()); println!("{}", c.get_num()); c.set_num(200); println!("{}", a.get_num()); println!("{}", b.get_num()); println!("{}", c.get_num()); }
100 100 100 200 200 200
リスト : write! の簡単な使用例 use std::io::{self, Write}; fn main () { let mut buff = Vec::new(); write!(&mut buff, "hello, world").unwrap(); write!(&mut buff, "{}, {}, {}", 1, 1.2345, "foo bar baz").unwrap(); io::stdout().write(&buff).unwrap(); }
hello, world1, 1.2345, foo bar baz
リスト : Display トレイトの定義 pub trait Display { fn fmt(&self, f: &mut Formatter) -> Result<(), Error>; }
リスト : Display トレイトの簡単な実装例 use std::fmt; struct Point { x: i32, y: i32 } impl fmt::Display for Point { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "({}, {})", self.x, self.y) } } fn main() { let a = Point { x: 0, y: 0 }; let b = Point { x: 10, y: 20 }; println!("{}, {}", a, b); }
(0, 0), (10, 20)
リスト : VecDeque の簡単な使用例 use std::collections::VecDeque; fn main() { // スタック (Stack) の動作 let mut s = VecDeque::new(); for x in 0 .. 10 { s.push_back(x); } println!("{:?}", s); while !s.is_empty() { println!("{}", s.pop_back().unwrap()); } // キュー (Queue) の動作 let mut q = VecDeque::new(); for x in 10 .. 20 { q.push_back(x); } println!("{:?}", q); while !q.is_empty() { println!("{}", q.pop_front().unwrap()); } }
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 9 8 7 6 5 4 3 2 1 0 [10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 10 11 12 13 14 15 16 17 18 19
リスト : LinkedList の簡単な使用例 use std::collections::LinkedList; fn main() { // スタック (Stack) の動作 let mut s = LinkedList::new(); for x in 0 .. 10 { s.push_back(x); } println!("{:?}", s); while !s.is_empty() { println!("{}", s.pop_back().unwrap()); } // キュー (Queue) の動作 let mut q = LinkedList::new(); for x in 10 .. 20 { q.push_back(x); } println!("{:?}", q); while !q.is_empty() { println!("{}", q.pop_front().unwrap()); } }
結果は VecDeque の簡単な使用例と同じ。
リスト : HashMap の簡単な使用例 use std::collections::HashMap; fn main() { let mut ht = HashMap::new(); ht.insert("foo", 1); ht.insert("bar", 2); ht.insert("baz", 3); ht.insert("oops", 4); println!("{:?}", ht); println!("{}", ht.contains_key("baz")); println!("{}", ht.contains_key("Baz")); println!("{:?}", ht.get("foo")); println!("{:?}", ht.get("Foo")); println!("{:?}", ht.remove("Oops")); println!("{:?}", ht.remove("oops")); println!("{:?}", ht.insert("foo", 100)); println!("{:?}", ht.insert("oops", 200)); for (k, v) in ht.iter() { println!("{}, {}", k, v); } }
{"oops": 4, "bar": 2, "foo": 1, "baz": 3} true false Some(1) None None Some(4) Some(1) None oops, 200 bar, 2 foo, 100 baz, 3
リスト : HashSet の簡単な使用例 use std::collections::HashSet; fn main() { let a: HashSet<_> = [1,2,3,4].iter().cloned().collect(); let b: HashSet<_> = [3,4,5,6].iter().cloned().collect(); println!("{:?}", a); println!("{:?}", b); println!("{}", a.contains(&1)); println!("{}", b.contains(&1)); let c: HashSet<_> = a.union(&b).cloned().collect(); println!("{:?}", c); let d: HashSet<_> = a.intersection(&b).collect(); println!("{:?}", d); let e: HashSet<_> = a.difference(&b).collect(); println!("{:?}", e); println!("{}", a.is_subset(&c)); println!("{}", b.is_subset(&c)); println!("{}", a.is_subset(&b)); }
{1, 2, 3, 4} {4, 6, 3, 5} true false {4, 5, 3, 6, 2, 1} {3, 4} {1, 2} true true false
リスト : Option の簡単な使用例 fn main() { let mut a: Option<i32> = Some(100); let mut b: Option<i32> = None; println!("{}", a.is_some()); println!("{}", b.is_none()); { let c = a.as_mut().unwrap(); *c = 200; } { let d = a.as_ref().unwrap(); println!("{}", d); } let e = a.take(); println!("{:?}", a); println!("{:?}", e); let f = b.take(); println!("{:?}", b); println!("{:?}", f); let g = e.map(|v| v * v); println!("{:?}", e); println!("{:?}", g); }
true true 200 None Some(200) None None Some(200) Some(40000)
リスト : AsRef トレイト pub trait AsRef<T> where T: ?Sized { fn as_ref(&self) -> &T; }
リスト : AsMut トレイト pub trait AsMut<T> where T: ?Sized { fn as_mut(&mut self) -> &mut T; }
リスト : 簡単な使用例 struct Foo<T> { item: T } impl<T> AsRef<T> for Foo<T> { fn as_ref(&self) -> &T { &self.item } } impl<T> AsMut<T> for Foo<T> { fn as_mut(&mut self) -> &mut T { &mut self.item } } fn get<T: AsRef<i32>>(n: &T) -> &i32 { n.as_ref() } fn inc<T: AsMut<i32>>(n: &mut T, m: i32) { *n.as_mut() += m; } fn main() { let mut a = Foo { item: 100 }; println!("{}", get(&a)); inc(&mut a, 100); println!("{}", get(&a)); }
100 200
リスト : Borrow トレイト pub trait Borrow<Borrowed: ?Sized> { fn borrow(&self) -> &Borrowed; }
リスト : HashMap のメソッド contains_key() の仕様 fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool where K: Borrow<Q>, Q: Hash + Eq
リスト : Borrow の簡単な使用例 use std::borrow::Borrow; use std::collections::HashMap; #[derive(Hash, Eq, PartialEq)] struct Foo { num: i32 } impl Borrow<i32> for Foo { fn borrow(&self) -> &i32 { &self.num } } fn main() { let mut ht: HashMap<Foo, i32> = HashMap::new(); ht.insert(Foo { num: 1 }, 100); ht.insert(Foo { num: 2 }, 200); ht.insert(Foo { num: 3 }, 300); println!("{:?}", ht.get(&1)); println!("{:?}", ht.get(&4)); println!("{:?}", ht.get(&Foo { num: 2 })); println!("{:?}", ht.get(&Foo { num: 5 })); }
Some(100) None Some(200) None
pub fn spawn<F, T>(f: F) -> JoinHandle<T> where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static,
リスト : スレッドの簡単な使用例 (1) use std::{thread, time}; fn foo(msg: &str, n: u64) { let m = time::Duration::from_millis(n); for _ in 1 .. 10 { println!("{}", msg); thread::sleep(m); } } fn main() { let t1 = thread::spawn(|| { foo("oops", 500); }); let t2 = thread::spawn(|| { foo("piyopiyo", 400); }); println!("{:?}", t1.join().unwrap()); println!("{:?}", t2.join().unwrap()); }
oops piyopiyo piyopiyo oops piyopiyo oops piyopiyo oops piyopiyo piyopiyo oops piyopiyo oops piyopiyo oops piyopiyo oops oops () ()
リスト : スレッドの簡単な使用例 (2) use std::thread; use std::time::Instant; // フィボナッチ数列 fn fibo(n: i64) -> i64 { if n < 2 { n } else { fibo(n - 1) + fibo(n - 2) } } fn main() { let s1 = Instant::now(); println!("{}", fibo(40)); let e1 = s1.elapsed(); println!("{}.{:03}秒経過しました。", e1.as_secs(), e1.subsec_nanos() / 1_000_000); let s2 = Instant::now(); let mut buff: Vec<_> = vec![]; buff.push(thread::spawn(|| fibo(40))); buff.push(thread::spawn(|| fibo(40))); for x in buff { println!("{}", x.join().unwrap()); } let e2 = s2.elapsed(); println!("{}.{:03}秒経過しました。", e2.as_secs(), e2.subsec_nanos() / 1_000_000); }
$ rustc -O sample61.rs $ ./sample61 102334155 0.372秒経過しました。 102334155 102334155 0.407秒経過しました。
pub fn channel<T>() -> (Sender<T>, Receiver<T>)
fn send(&self, t: T) -> Result<(), SendError<T>> fn recv(&self) -> Result<T, RecvError>
リスト : チャネルの簡単な使用例 use std::thread; use std::sync::mpsc; fn fibo(n: i64) -> i64 { if n < 2 { n } else { fibo(n - 1) + fibo(n - 2) } } fn main() { let (tx, rx) = mpsc::channel(); for x in vec![40, 39, 38, 37] { let tx = tx.clone(); thread::spawn(move || tx.send(fibo(x)).unwrap()); } for _ in 0 .. 4 { println!("{}", rx.recv().unwrap()); } }
24157817 39088169 63245986 102334155
fn lock(&self) -> LockResult<MutexGuard<T>>
リスト : Arc と Mutex の簡単な使用例 use std::thread; use std::sync::{Arc, Mutex}; fn main() { let data = Arc::new(vec![10, 20, 30, 40]); for i in 0 .. 4 { let data = data.clone(); thread::spawn(move || { println!("{}", data[i]); }).join().unwrap(); } let data1 = Arc::new(Mutex::new(vec![1, 2, 3, 4])); for i in 0 .. 4 { let data1 = data1.clone(); thread::spawn(move || { let mut buff = data1.lock().unwrap(); buff[i] += 10; println!("{}", buff[i]); }).join().unwrap(); } println!("{:?}", data1); }
10 20 30 40 11 12 13 14 Mutex { data: [11, 12, 13, 14], poisoned: false, .. }
fn read(&self) -> LockResult<RwLockReadGuard<T>> fn write(&self) -> LockResult<RwLockWriteGuard<T>>
リスト : RwLock の簡単な使用例 (1) use std::sync::RwLock; fn main() { let lock = RwLock::new(123); { let r1 = lock.read().unwrap(); let r2 = lock.read().unwrap(); println!("{}, {}", *r1, *r2); //let mut w1 = lock.write().unwrap(); ブロックされる //*w1 = 456; //println!("{}", *w1); } { let mut w1 = lock.write().unwrap(); *w1 = 456; println!("{}", *w1); //let mut w2 = lock.write().unwrap(); ブロックされる //*w2 = 789; //println!("{}", *w2); //let r3 = lock.read().unwrap(); ブロックされる //println!("{}", *r3); } }
123, 123 456
リスト : RwLock の簡単な使用例 (2) use std::{thread, time}; use std::sync::{Arc, RwLock}; fn main() { let lock = Arc::new(RwLock::new(1)); let t1; let t2; { let lock = lock.clone(); t1 = thread::spawn(move || { for _ in 0 .. 10 { match lock.try_read() { Ok(r) => println!("read data {}", *r), _ => println!("Can't read data") } thread::sleep(time::Duration::from_millis(500)); } }); } { let lock = lock.clone(); t2 = thread::spawn(move || { for _ in 0 .. 10 { match lock.try_write() { Ok(mut w) => { *w+= 1; println!("write data {}", *w); } _ => println!("Can't write data") } thread::sleep(time::Duration::from_millis(500)); } }); } t1.join().unwrap(); t2.join().unwrap(); }
read data 1 write data 2 read data 2 Can't write data read data 2 Can't write data read data 2 Can't write data read data 2 Can't write data write data 3 Can't read data read data 3 Can't write data read data 3 Can't write data read data 3 Can't write data read data 3 Can't write data
read data 1 Can't write data write data 2 read data 2 write data 3 read data 3 write data 4 read data 4 write data 5 read data 5 write data 6 read data 6 write data 7 read data 7 write data 8 read data 8 write data 9 read data 9 write data 10 read data 10