目次

Rustの勉強[CLI作成編 その12 & クロージャ その1]

(更新: )ぎじゅつ

はじめに

#

NO IMAGEThe Rust Programming Language 日本語版 - The Rust Programming Language 日本語版
を読んでいる

今日こそ終わらせる

お勉強

#

メモ

#

NO IMAGE標準出力ではなく標準エラーにエラーメッセージを書き込む - The Rust Programming Language 日本語版

  • エラーメッセージを書くらしい

現時点では、すべての出力をprintln!関数を使用して端末に書き込んでいます。多くの端末は、 2種類の出力を提供します: 普通の情報用の標準出力(stdout)とエラーメッセージ用の標準エラー出力(stderr)です。 この差異のおかげで、ユーザは、エラーメッセージを画面に表示しつつ、 プログラムの成功した出力をファイルにリダイレクトすることを選択できます。

  • たしかにVimと連携するときはstdout設定にするほうがいいみたいなものよくみたな
cargo run >output.txt
  • こうやったらエラーも書き込まれちゃうか
  • 考えてなかったわ

標準ライブラリは、 標準エラーストリームに出力するeprintln!マクロを提供しているので、 println!を呼び出してエラーを出力していた2箇所を代わりにeprintln!を使うように変更しましょう。

  • 便利

  • 本当だ、実行したら何も書き込まれなくなった

  • お、minigrep終わった!!!

NO IMAGE関数型言語の機能:イテレータとクロージャ - The Rust Programming Language 日本語版

  • まっていたぞ、クロージャとイテレータ
  • 関数型プログラミングに興味がありけり

クロージャとイテレータをマスターすることは、慣用的で速いRustコードを書くことの重要な部分なので、 この章を丸ごと捧げます。

  • めちゃくちゃ良さそう

  • まずはクロージャから

  • 計算に数秒かかることが問題と記載されている

use std::thread;
use std::time::Duration;

fn simulated_expensive_calculation(intensity: u32) -> u32 {
    // ゆっくり計算します
    println!("calculating slowly...");
    thread::sleep(Duration::from_secs(2));
    intensity
}
  • なるほどね
fn main() {
    let simulated_user_specified_value = 10;
    let simulated_random_number = 7;

    generate_workout(simulated_user_specified_value, simulated_random_number);
}
  • fmfm
fn generate_workout(intensity: u32, random_number: u32) {
    if intensity < 25 {
        println!(
            // 今日は{}回腕立て伏せをしてください!
            "Today, do {} pushups!",
            simulated_expensive_calculation(intensity)
        );

        println!(
            // 次に、{}回腹筋をしてください!
            "Next, do {} situps!",
            simulated_expensive_calculation(intensity)
        );
    } else {
        if random_number == 3 {
            // 今日は休憩してください!水分補給を忘れずに!
            println!("Take a break today! Remember to stay hydrated!");
        } else {
            println!(
                // 今日は、{}分間走ってください!
                "Today, run for {} minutes!",
                simulated_expensive_calculation(intensity)
            );
        }
    }
}
  • とりあえずifがいっぱいあって無駄な記述ってことかな

simulated_expensive_calculation関数を1回だけ呼び出すように、 このコードをリファクタリングしたいです。

  • ここが本質そう
fn generate_workout(intensity: u32, random_number: u32) {
    let expensive_result = simulated_expensive_calculation(intensity);

    if intensity < 25 {
        println!("Today, do {} pushups!", expensive_result);
        println!("Next, do {} situps!", expensive_result);
    } else {
        if random_number == 3 {
            println!("Take a break today! Remember to stay hydrated!");
        } else {
            println!("Today, run for {} minutes!", expensive_result);
        }
    }
}

多くの方法でトレーニングプログラムを再構築することもできます。 1番目にsimulated_expensive_calculation関数への重複した呼び出しを変数に抽出しようとしましょう。

  • なんかjsみたい

simulated_expensive_calculationの本体全体を実際に、ここで導入しているクロージャ内に移すことができます。

let expensive_closure = |num| {
    println!("calculating slowly...");
    thread::sleep(Duration::from_secs(2));
    num
};

このクロージャには、numという引数が1つあります: 2つ以上引数があるなら、 |param1, param2|のように、カンマで区切ります。

  • もっとjsのアロー関数みたいになった

クロージャが定義されたので、ifブロックのコードを変更して、そのコードを実行するクロージャを呼び出し、結果値を得ることができます。

fn generate_workout(intensity: u32, random_number: u32) {
    let expensive_closure = |num| {
        println!("calculating slowly...");
        thread::sleep(Duration::from_secs(2));
        num
    };

    if intensity < 25 {
        println!("Today, do {} pushups!", expensive_closure(intensity));
        println!("Next, do {} situps!", expensive_closure(intensity));
    } else {
        if random_number == 3 {
            println!("Take a break today! Remember to stay hydrated!");
        } else {
            println!("Today, run for {} minutes!", expensive_closure(intensity));
        }
    }
}
  • おおおおお
  • マジでjsみたいだな

まとめ

#
  • minigrep完遂、stderrってeprintln!マクロでいいのが勉強になった

  • クロージャってのはjsでよくあったアロー関数的な認識になった

  • 関数として定義するには短いし、使いまわしすぎることのないものを変数に入れられるしくみの認識

  • 次はここやる

NO IMAGEクロージャ:環境をキャプチャする匿名関数 - The Rust Programming Language 日本語版