Rust雑入門2

お品書き

  • Cargoの使い方
  • Docopt.rsについて

Cargo

Cargoとは

  • Rustのパッケージマネージャー
  • RubyでいうBundler(作者が同じ)
  • Cargo.tomlに依存パッケージなどを書けば
  • Cargo run など必要な時に取得・コンパイルしてくれる
  • Rustのオフィシャルツール
  • パッケージマネージャーの決めてる欠けるGoに比べるとすごく楽
  • Rustをインストールした時点で一緒にインストールされている

Cargo

基本コマンド

  • cargo new でライブラリの開発プロジェクト開始
  • cargo new --bin では実行用のバイナリを書く
  • cargo run で実行
  • cargo test でテストを実行
  • cargo build でビルド(開発デバッグ用)
  • cargo build --release で最適化してビルド
  • cargo help を見ればOK
  • じっくり学びたい人は Cargo Guideを参照

Cargo

Hello World

with Cargo

CargoでHello World!

cargo new --bin hello
cd hello
cargo run

ビルドされ、"Hello, world!" と出力される

CargoでHello World!

├── .git
├── .gitignore
├── Cargo.toml
└── src
    └── main.rs

hello ディレクトリの構成

CargoでHello World!

├── .git
├── .gitignore
├── Cargo.toml
└── src
    └── main.rs

hello ディレクトリの構成

デフォルトでGitがバージョン管理に使われる

CargoでHello World!

├── .git
├── .gitignore
├── Cargo.toml
└── src
    └── main.rs

hello ディレクトリの構成

パッケージの情報と依存パッケージなどを書き込む

インストールされたパッケージはCargo.lockで

バージョンが固定される

CargoでHello World!

├── .git
├── .gitignore
├── Cargo.toml
└── src
    └── main.rs

hello ディレクトリの構成

cargo runで実行されるのがsrc/main.rs

このファイルを開くとhello worldを出力するプログラムが書いてある。(仕様)

今回はこれを編集していく

Docopt

docopt

  • コマンドのヘルプをパーズして、引数やオプションを利用できる便利なライブラリ
  • 各言語にライブラリが存在する
  • ただしGo版はあまりイケてない(type assertion)
  • Cargoでも使われている

Docoptとは

docopt

  • 今回もなんちゃってcat
  • 標準入力無視
  • -nだけ対応

プロジェクトを開始

cargo new --bin cat

docopt

  • Cargo.tomlに[dependencies]を追加
  • docopt = "*" で最新版をインストール
  • rustc-serializeも必要なので入れる

Docoptのインストール

# Cargo.toml
[dependencies]
docopt = "*"
rustc-serialize = "*"

docopt

Docoptでパーズした結果のargsをprintln!で表示する例(開発用)。各行を解説していく!

extern crate rustc_serialize;
extern crate docopt;

use docopt::Docopt;

const USAGE: &'static str = "
Usage:
    cat [options] [<file>...]

Options:
    -h, --help  Display this message
    -n          Number the output lines, starting at 1.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_file: Option<Vec<String>>,
    flag_n: bool,
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());
    println!("{:?}", args);
}

docopt

extern crateはRubyでいうrequire

useについは前回のスライドを参照

extern crate rustc_serialize;
extern crate docopt;

use docopt::Docopt;

docopt

const &'static str は定数

const USAGE: &'static str = "
Usage:
    cat [options] [<file>...]

Options:
    -h, --help  Display this message
    -n          Number the output lines, starting at 1.
";

docopt

catの引数やオプションの書式

[]は省略可能

-はフラグ、値がない場合はbool

<>は引数 ... は可変

詳しくは以下を参照

Qiita: docoptでドキュメントとともにコマンドラインツールを作る

const USAGE: &'static str = "
Usage: cat [options] [<file>...]

Options:
    -h, --help  Display this message
    -n              Number the output lines, starting at 1.
";

docopt

deriveは指定したTraitを自動で実装させるアトリビュート

Debugはprintln!("{:?}")で、表示できるようにするTrait、{}で表示させるにはDisplay

RustcDecodableはDocOptが使用している

(今回に限っての話)

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_file: Option<Vec<String>>,
    flag_n: bool,
}

docopt

Argsというstructを定義している

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_file: Option<Vec<String>>,
    flag_n: bool,
}

docopt

メンバ変数、プロパティの定義といったところ

メソッドの実装はimplを使って別に定義する

メソッド定義については別の機会に...

 

[<file>...]は省略可能なのでOption

<file>...は文字列の配列になるのでVec<String>

今回はあえて省略可能にしている

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_file: Option<Vec<String>>,
    flag_n: bool,
}

docopt

-nは値なしなのでbool

-nが指定されているとtrue

省略の場合はfalseが入る

 

実際に入ってくる値をcargo runで確かめよう

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_file: Option<Vec<String>>,
    flag_n: bool,
}

docopt

cargo runで、実行対象に引数を渡す時は--をつけて、その後ろに渡す

--より前はcargo run自体の引数(--verboseなど)

cargo run -- -n a b c

docopt

引数がちゃんとパーズされて取れていることがわかる

cargo run -- -n a b c
#      Running `target/debug/cat -n a b c`
# Args { arg_file: Some(["a", "b", "c"]), flag_n: true }

続く...

Rust雑入門2

By dopin

Rust雑入門2

  • 1,161