気を散らすノート

色々と散った気をまとめておくところ.論文読んだり自分で遊んだりする.たぶん.

Rust で advent するときのファイル構成

じぶん advent calendar 2019 の 2日目の記事,になるかもしれない記事です.

Rust のモジュールシステムは 2018 edition で大きく変化し,だいぶ直観的に動いてくれるようになりました.これについては the book にも詳しいのですが,2015版を中途半端に理解した状態からだとあらゆる点で混乱しがちだし,「結局どうやねん」っていうところについては Rustのモジュールの使い方 2018 Edition版 | κeenのHappy Hacκing Blog が読みやすいです.

でも,とりあえず理解はいいから昨日から始まった advent of code を rust で解きたいぜって時にどういう作りにすればいいか,というのが本日の記事.

  • 初日から25日まで別の実行ファイルを簡単に作りたい
  • 便利函数みたいなのは一度定義して使いまわしたい

のを目標にします.$ cargo new --bin aoc2019 から初めます.こういう状態

$ tree
.
├── Cargo.toml
└── src
    └── main.rs

複数実行ファイル

Rust はこの点非常に楽で,src/bin/[filename].rs があれば cargo run --bin [filename] で呼ぶことができます. $ mkdir src/bin でok.

ライブラリの作成と呼び出し

随分直観的になった.lib.rsが偉くて,src 直下に各宣言された名前のモジュールを置け,ディレクトリ作れば下に掘っていける. こういうつくりにして

src/
├── bin
│   └── hithere.rs
├── lib.rs
├── greetings.rs
└── greetings
    └── morning.rs

src/lib.rs:

pub mod greetings;

pub fn helloworld() {
    println!("hello, world!");
}

src/greetings.rs:

pub mod morning;

pub fn hi() {
    println!("HI");
}

src/greetings/morning.rs:

pub fn ohayo() { println!("おはようございます"); }

こうすれば bin/ 下のファイルからは std::collections と同様の感じで使うことができる.例えば

use aoc2019::greetings::morning;

fn main(){
    aoc2019::helloworld();
    aoc2019::greetings::hi();
    morning::ohayo();
}

結構気軽に書きやすい作りにすることができました.Project Euler とかでも同様の構成でうまくできると思います(ただ Rust の場合整数全体に generic な函数を書いたりするのがやけに面倒なのはつらいところ.num とか使うと楽できるっぽい).

ちなみに Haskell+stack は複数の実行ファイル作ろうと思うとこうするしかないっぽくてマジでめんどくさいです.或いは引数を読んで適宜の解を呼ぶ Main.hs を造るかだけど……どうにかならんか.