8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rustのfold

Posted at

ふつうの関数型言語の感覚でfoldすると、参照で詰む。

例題として、任意個の整数の最大公約数の計算を考える。

誤ったコード

fn gcd(a: u32, b: u32) -> u32 {
    assert!(a != 0 || b != 0);
    if a == 0 { b }
    else { gcd(b % a, a) }
}

fn main() {
    let nums = [799459, 28823, 27347];
    if let Some((head, tail)) = nums.split_first() {
        println!("gcd = {}", tail.iter().fold(head, gcd));
    }
}

正しいコード

fn gcd(a: u32, b: u32) -> u32 {
    assert!(a != 0 || b != 0);
    if a == 0 { b }
    else { gcd(b % a, a) }
}

fn main() {
    let nums = [799459, 28823, 27347];
    // &head に注意
    if let Some((&head, tail)) = nums.split_first() {
        // &b に注意
        println!("gcd = {}", tail.iter().fold(head, |a,&b| gcd(a,b)));
    }
}
  • slice::split_firstは参照を返すので、&headで受けて参照を剥がさなければならない
  • foldする関数の第二引数には参照が渡ってくるので、&bで受けて参照を剥がさなければならない

foldに渡す関数の引数と戻り値が参照である場合は、この罠には嵌まらない。

8
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?