🦀

[Rust][Idioms]引数に借用型を使用する

2022/12/03に公開

Rustで実装がある程度できるようになってきたら、Design patterns in Rustを学習することをオススメします。

特に、RustでBlockChainの低レイヤーを開発をする人は、深くRustを理解しておくべきです。

今回は

引数に借用型を使用する

というRustのIdiomを紹介します。

環境

rustc 1.64.0

概要

関数の引数にどの引数型を使うかを決めるときに、deref強制のターゲットを使うことでコードの柔軟性を高めることができます。

つまり、所有型を借りるよりも借用型を使う方が常に望ましいということです。

例えば、&String よりも &str、&Vec<T> よりも &[T]、あるいは &Box<T> よりも &T を使うということです。

(スライスは、配列やベクタなどのある位置を指し[T]のように書きます。そして、常に参照されます。)

具体例

fn three_vowels(word: &String) -> bool {
    let mut vowel_count = 0;
    for c in word.chars() {
        match c {
            'a' | 'e' | 'i' | 'o' | 'u' => {
                vowel_count += 1;
                if vowel_count >= 3 {
                    return true
                }
            }
            _ => vowel_count = 0
        }
    }
    false
}


fn main() {
    let ferris = "Ferris".to_string();
    let curious = "Curious".to_string();
    println!("{}: {}", ferris, three_vowels(&ferris));
    println!("{}: {}", curious, three_vowels(&curious));
}

three_vowels関数は引数が&Stringなので、"Ferris"のような&str型は利用できません。
なので、to_string()を利用してString型にしてから&Stringにして値を渡す必要があります。

このコードは使い勝手が悪いので、以下のように変更します。

fn three_vowels(word: &str) -> bool {
    let mut vowel_count = 0;
    for c in word.chars() {
        match c {
            'a' | 'e' | 'i' | 'o' | 'u' => {
                vowel_count += 1;
                if vowel_count >= 3 {
                    return true
                }
            }
            _ => vowel_count = 0
        }
    }
    false
}


fn main() {
    // &strを呼び出す
    println!("Ferris: {}", three_vowels("Ferris"));
    println!("Curious: {}", three_vowels("Curious"));

    let ferris = "Ferris".to_string();
    let curious = "Curious".to_string();
    // &Stringも呼び出し可能
    println!("{}: {}", ferris, three_vowels(&ferris));
    println!("{}: {}", curious, three_vowels(&curious));

}

&Stringを&strに変更します。
これにより、&Stringでも&strのどちらを引数に入れても関数を呼び出すことができます

これが可能な理由は、Stringから&strへの変換は、暗黙に実行されるためです。

rustではこういった場合、引数に借用型を使用するのが慣例になっています。

参考記事

https://rust-unofficial.github.io/patterns/idioms/coercion-arguments.html

Discussion