Perl日記

日々の知ったことのメモなどです。Perlは最近やってないです。

Rust で自動でデリファレンスされるやつのメモ2

https://doc.rust-jp.rs/book-ja/ch05-03-method-syntax.html#-%E6%BC%94%E7%AE%97%E5%AD%90%E3%81%AF%E3%81%A9%E3%81%93%E3%81%AB%E8%A1%8C%E3%81%A3%E3%81%9F%E3%81%AE

Rustには->演算子の代わりとなるようなものはありません; その代わり、Rustには、 自動参照および参照外しという機能があります。Rustにおいてメソッド呼び出しは、 この動作が行われる数少ない箇所なのです。


動作方法はこうです: object.something()とメソッドを呼び出すと、 コンパイラはobjectがメソッドのシグニチャと合致するように、自動で&か&mut、*を付与するのです。 要するに、以下のコードは同じものです:


p1.distance(&p2);
(&p1).distance(&p2);

let s = "foo".to_string();
let ss = &s;
let sss = &ss;
assert_eq!(3, sss.len());
assert_eq!(3, (***sss).len());

今日得た学びとしては、usize 型の + (std::ops::Add) は、usize を返すので、&usize を使ってるときの配列やベクタの添え字(usize が必要となる)でこんな感じになった。

let v: Vec<u32> = vec![11, 22, 33, 44, 55];
let i: usize = 3;
let j = &i;
assert_eq!(44, v[*j]);  // j は &usize 型だから、添え字にできず、* のデリファレンスが要る
assert_eq!(55, v[j + 1]); // (*j).add(1) で 新規の usize 型の値が返ってくるのでそれがそのまま添え字になる

手動でのデリファレンスが必要だったり不要だったりした。

Rust で Vector の先頭の要素を取り出したり押し込んだりするときは VecDeque を使う

通常の Vector では push() と pop() しかなくて、いずれも配列の最後の要素に対してしか操作できない。先頭の要素を取り出したり、要素を押し込んだりするためには、std::collections::VecDeque を使うのが良いようだ。
Ruby の Array#shift とか Array#unshift と同じ動きのやつ)

VecDeque in std::collections - Rust

use std::collections::VecDeque;

fn main() {
    // いつもの Vec
    let mut v: Vec<i32> = Vec::new();
    v.push(1); // 末尾に追加
    v.push(2);
    v.push(3);
    v.push(4);
    v.pop(); // 末尾から取得して削除 (Option<T>)
    assert_eq!(vec![1, 2, 3], v);

    let mut v2: VecDeque<i32> = VecDeque::new();
    v2.push_back(1); // Vec push と同じ
    v2.push_back(2);
    v2.push_back(3);
    v2.push_back(4);
    v2.pop_front(); // 先頭から取得して削除 (Option<T>)
    assert_eq!(vec![2, 3, 4], Vec::from(v2.clone()));

    v2.push_front(1);  // 先頭に要素を押し込む
    v2.pop_back();    // Vec pop と同じ
    assert_eq!(vec![1, 2, 3], Vec::from(v2.clone()));
}

Vector とはメモリの使い方が違うらしく、ソートとかスライスとかを期待通りに取得するためには、その前に make_contiguous() で合体しないといけならしいので注意するというメモ。