Rust 入門 簡単な関数を書いてみる(1)

Rust 入門その2

前回、FizzBuzzを書いてとりあえずコンパイルと実行の仕方は判ったので、次ももう少しまともなコードを書いてみることにする。
適当な題材はないかと考えて、以前C#で書いた住所の文字列から都道府県や市区町村を分割するコードがあるので、それをRustで書き直してみる。
想像以上に手間取ったので、とりあえず住所から都道府県を切り出す部分のみ。

やりかたは都道府県の名称を正規表現で切り出すだけなのだが、勝手が判らず簡単そうなトコでも思ったようにいかない。

引っかかったのは以下の箇所。

  • 静的な配列の定義のしかた。
  • タプルの配列から要素を取り出し一つの文字列に連結する方法
  • 正規表現の使い方
  • Stringと&strの違い などなど

関数はRustっぽくResultを返すようにしたけど、単純に都道府県とそれ以降のタプルを返す方が後の処理が単純で良いかもしれない。

extern crate regex;
use regex::Regex;

const PREFECTURES:[(&str, &str); 47] = [
        ("01","北海道"), ("02","青森県"), ("03","岩手県"), ("04","宮城県"), ("05","秋田県"),
        ("06","山形県"), ("07","福島県"), ("08","茨城県"), ("09","栃木県"), ("10","群馬県"),
        ("11","埼玉県"), ("12","千葉県"), ("13","東京都"), ("14","神奈川県"), ("15","新潟県"),
        ("16","富山県"), ("17","石川県"), ("18","福井県"), ("19","山梨県"), ("20","長野県"),
        ("21","岐阜県"), ("22","静岡県"), ("23","愛知県"), ("24","三重県"), ("25","滋賀県"),
        ("26","京都府"), ("27","大阪府"), ("28","兵庫県"), ("29","奈良県"), ("30","和歌山県"),
        ("31","鳥取県"), ("32","島根県"), ("33","岡山県"), ("34","広島県"), ("35","山口県"),
        ("36","徳島県"), ("37","香川県"), ("38","愛媛県"), ("39","高知県"), ("40","福岡県"),
        ("41","佐賀県"), ("42","長崎県"), ("43","熊本県"), ("44","大分県"), ("45","宮崎県"),
        ("46","鹿児島県"), ("47","沖縄県")    
    ];

// 住所から都道府県とそれ以降を分割する
fn get_prefecture(address: &str) -> Result<(String, String), String> {
    let prefectures = PREFECTURES.iter().map(|x| x.1).collect::<Vec<&str>>().join("|");
    let pattern = format!("^({})(.+*)$", prefectures);
    let re = Regex::new(&pattern).unwrap();

    match re.captures(address) {
        Some(m) => Ok(((&m[1]).to_string(), (&m[2]).to_string())),
        None => Err("No match".to_string())
    }
}

// main
fn main() {
    match get_prefecture("大阪府大阪市北区ほげほげ1-2-3") {
        Ok(ret) => println!("{:?}", ret),
        Err(e) => println!("{}", e)
    };
}

DXライブラリで、描画した図形に穴をあける

DXライブラリを利用して児童向けの学習教材を作成しているのだが、MakeScreen()したグラフィックに描画した矩形などの図形に穴をあけて背景を透過させる必要が出てきた。
DrawCircle() などの関数に指定する色に透明色?が指定できれば良いのだが、DXライブラリで使用する色コードには透明度の情報はない。
最初、マスク関係関数の機能を利用すればできそうかなと考えたが、マスクデータがDXライブラリのグラフィックではなくバイナリの配列データで用意する必要があり面倒。 もうちょっと手軽にできる方法はないかと検索してみたら、DXライブラリ質問掲示板で 「MakeGraph() による背景の透明化」という記事を見つけた。

その記事によると、SetDrawBlendMode()で、乗算モードを指定してパラメーターに0を指定することで、描画時のアルファチャンネルの値を0にすることができるらしい。この時、乗算モードを指定するのをリファレンスに記載されている DX_BLENDMODE_MULA(11)ではなく、DX_BLENDMODE_MUL(4)を指定しなくてはいけない。ここら辺の仕組みリファレンスに記載がないので何がどうしてどうなってるのかさっぱりだが、とりあえず試してみると期待していた描画ができた。

// ■ 穴の開いた矩形を描画する。

// 矩形を描く
DX.DrawBox(0, 0, 640, 480, red , DX.TRUE);
// ブレンドモードで乗算モードを指定
DX.SetDrawBlendMode(DX.DX_BLENDMODE_MUL, 0);
// ここで描画した円はアルファチャンネルが0で描画されるため透明になる。
// 結果として透明になるので指定する色は何色でも良い。
DX.DrawCircle(100, 100, 50, WHITE, DX.TRUE); 
// ブレンドモードを元に戻す
DX.SetDrawBlendMode(DX.DX_BLENDMODE_NOBLEND, 255);

DXライブラリ置き場 HOME

PythonではじめるiOSプログラミング

いつもの如くジュンク堂を冷やかしてたら発売されていたので購入。
iOSで動作するPythonの開発環境である Pythonista3 の解説書。
著者の掌田津耶乃は確かMac関連の雑誌でライターをしていた人で、最近はやたらめったらビギナー向けの入門書を書きまくってる印象の人。普段はこの人の対象とする読者層からずれてるので買うことはないが、Pythonista3 の解説書ということで無条件購入。

内容は1章が概説、2章がNumPy, SymPy, matplotlib のざっくりとした解説、3章からがPythonista固有のUIライブラリや2Dゲーム開発用の SceneやNode、iOS固有の機能を利用するためのライブラリとそのサンプルプログラムの解説となっている。ちなみに、Python については巻末の付録で文法についての簡易リファレンスがついているだけで解説はない。したがってある程度のPythonの知識のある人が前提の本になっている。Pythonに関する入門書は腐るほどあるのでその判断は正しいと思うが、それなら、2章のNumPyなどの数学ライブラリの解説もいらんのではないかと思った。

3章以降のPythionista3固有のライブラリの解説は、さすがに入門書をたくさん書いているだけあって熟れた感じでさくさく読める。いくつか趣味に合わない表現などがあって気になる箇所はあったものの、思ってた以上に入門書としてキチンとした内容で、ちょっと掌田津耶乃さんなめてましたスイマセンという気持ちに。

Rust 入門 : FizzBuzzを書いてみる。

Rust に入門してみる。

最初のプログラムということで、難しいことを考えず素直ににFizzBuzzを書いてみる。
若いころは最初に書くプログラムといえば Hello world と相場は決まっていたが、最近はFizzBuzzなのだそうだ。そもそも、Rust だとプロジェクトを生成すると雛形のソースが Hello world になっておりわざわざ書く必要もない。

まず、適当なディレクトリで、

% cargo new fizz_buzz
  Created binary (application) `fizz_buzz` package

とやって、プロジェクトを作成して、生成されたmain.rsを書き換える。
1から100までの数列の生成方法と、パターンマッチのやりかたを適当にググって書いて見ると以下のような感じに。

// Fizz Buzz
fn main() {
    for n in 1..101 {
        match n {
            x if (x % 3 == 0 && x % 5 == 0) => println!("Fizz Buzz"),
            x if (x % 3 == 0) => println!("Fizz"),
            x if (x % 5== 0) => println!("Buzz"),
            _ => println!("{}", n)
        }
    }
}

cargo run でコンパイルと実行ができるようなのでやってみる。

% cargo run
   Compiling fizz_buzz v0.1.0 (/Users/osamu/Projects/rust/fizz_buzz)
    Finished dev [unoptimized + debuginfo] target(s) in 0.22s
     Running `target/debug/fizz_buzz`
1
2
Fizz
4
Buzz
Fizz
...

とりあえずエラーもなく動いた。