Rust (2)

『単純な脳、複雑な「私」』(ブルーバックス)なんてのを読んだ。 オイラーの偏見かも知れないけど、脳化学って、どこか胡散臭い思いを持ってたんで、それを 払拭出来るかなと勇気を出した次第。

薬学部で研究に勤しむ脳化学者が、母校で高校生相手に出前講義を行ったものを収録したとか。 有体離脱ってあるの? とか、吊り橋の上の告白は成功率が高いとか、面白い話が出てきて、 おいらも聞きたかったな。

脳の不思議が、著者の用意した資料 で、体験出来る。この中で、おいらの興味を引いたのは、コホーネンの自己組織化マップって やつ。

これ、人がものを学習していく様子にすごく似ているとか。幼児が言葉を覚えるのは、回りから 勉強せいって強制されるわけでもないのに、親や周囲の人の会話を聞くだけで、自発的に 単語の意味や使い方を学習してく。脳味噌の中で超凄い事が行われているかと言うと、 そうでなくても出来るんじゃねぇってのが、先のシュミレーション。

色の違いで分類する例だけど、どうやってるかと言うと、 ランダムな色のマスがある。 手元で適当な色(C)を決める。 マスの中で似てる色を探す。 見つかったマスとその周辺のマスに、(C)の色を少し混ぜる。この操作の繰り返しで、 似たもの(色)が集まってくる。詳しい事は、 数学は脳を模倣する!?に出てた。

これと同じ方針を単語に適用して、本に書かれた概要をまとめるという研究も行われているとか。 流行のBig Data解析とか違うのかな?

後、興味を引いたのは脳に繋がっている各種センサーの話。自然界はべき乗則に 支配されてる。その例として情報科学のあれこれ から、 自然界はべき乗則で支配されるってのを 引いておられた。これも面白いね。

そして、最後にリカージョン、再帰の話に行き着いた。脳と再帰がどう結びつくの? 自分の心を考える自分がいる。でも、そんな自分を考える自分がいる。。。。

再帰の基底条件は何なんでしょうね?

Rustの資料とか

さてはて、これからRustを触って行こうと思うんだけど、何か資料はないかしらと思って Qiitaから探してきたよ。取り合えず見とけって事で。

本が出れば、統一的と言うか 網羅的に知識が得られるだろうけど、それはちゃんと1.0になってからだろうしね。 今は絶望に近い。まてまて、そういう言い方より、『夜明け前』って言う方がいいぞ。

Rustを触ってみる

Rustのコードを最低限理解するための例

Pythonの組み込み関数とRustの対応関係

Rust by example

プログラミング言語RustでFizz-Buzzしてみる

Rustの他言語関数インターフェース(FFI)のガイド

Rust言語で簡単なcatコマンドを実装してみた

Rustで自作シェルもどきを作る(単純なコマンド実行編)

Rustのマクロのガイド

rustのライブラリィって有るの?

まだ正式な版になってないので、Librariesなんて開発してる奇特な人は居ないだろうと 思っていたけど、ボチボチでんなあ。

でも、この人達、パイオニアーと言うかディスカバリーと言うか、エクスプローラーと言うか、 名にコレ? 全部宇宙船とか人工衛星の名前じゃん!

Community libraries

Cargo Central

Cargo -- All Crates 何と言っても、ここが一番の集積地ですよ。

何はなくともCSV

例によって例のごとく例をやるんで、CSVだな。上のパイオニアーの人が用意してくれていた。

rust-csv

まずは、そろそろと行く。用意したcsvデータは、例によって血圧測定値。本当は年も 改まったので、使用電力と外気温のデータでも用意しようと思ったんだけど、電力会社 からの請求書3年分を女房が整理しちゃったものだから、なくなく代わり映えしない データで我慢。

発句は例に出てたもののうちStracutを使った物にした。で、実行してみると

[sakae@fedora bld]$ cargo run
    Updating registry `https://github.com/rust-lang/crates.io-index`
 Downloading rustc-serialize v0.2.9
 Downloading csv v0.12.10
   Compiling rustc-serialize v0.2.9
../../.cargo/registry/src/github.com-1285ae84e5963aae/rustc-serialize-0.2.9/src/base64.rs:189:6: 189:16 error: attempt to implement a nonexistent trait `fmt::Debug`
../../.cargo/registry/src/github.com-1285ae84e5963aae/rustc-serialize-0.2.9/src/base64.rs:189 impl fmt::Debug for FromBase64Error {
   :
error: aborting due to 22 previous errors
Build failed, waiting for other jobs to finish...
Could not compile `rustc-serialize`.

rust-csvのステータスを見るとPASSしてるし、、、きっと本体のrustcが古いからだろうと 当たりを付けて、本体をupdateしたよ。また、cargo updateもエラーに良く効く対処方法です。 こちらは手間要らずなんで、悩んだ時はお試しあれ。運が良ければ、すっきりさっぱりに なる事でしょう。

そしたら、

[sakae@fedora bld]$ cargo run
   Compiling rustc-serialize v0.2.9
   Compiling csv v0.12.10
   Compiling bld v0.0.1 (file:///home/sakae/rust/bld)
src/main.rs:4:1: 4:51 error: can't find crate for `rustc_serialize`
src/main.rs:4 extern crate "rustc-serialize" as rustc_serialize;
              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
Could not compile `bld`.

To learn more, run the command again with --verbose.

今度はコンパイルOK、実行NG。詳しくはverboseを付けて勉強しろとな。

[sakae@fedora bld]$ cargo run --verbose
       Fresh rustc-serialize v0.2.9
       Fresh csv v0.12.10
   Compiling bld v0.0.1 (file:///home/sakae/rust/bld)
     Running `rustc src/main.rs --crate-name bld --crate-type bin -g --out-dir /home/sakae/rust/bld/target --emit=dep-info,link -L dependency=/home/sakae/rust/bld/target -L dependency=/home/sakae/rust/bld/target/deps --extern csv=/home/sakae/rust/bld/target/deps/libcsv-edde0b28f1d2e123.rlib`
src/main.rs:4:1: 4:51 error: can't find crate for `rustc_serialize`
src/main.rs:4 extern crate "rustc-serialize" as rustc_serialize;
              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

これって、rustc-serializeが見つからんって事。そうすると、Cargo.tomlとか言う 設定ファイルに書いておかないといけないのかな? 何となく、こんなシチエーションを clojureのleinで経験したような。。。

[sakae@fedora bld]$ cat Cargo.toml
[dependencies]
csv = "*"
rustc-serialize = "*"

[package]
name = "bld"
version = "0.0.1"
authors = ["sakae"]

今度はどうだー?

[sakae@fedora bld]$ cargo run
     Running `target/bld`
(15010121, 120): 68
(15010205, 118): 73
(15010221, 101): 60

うん、旨くいった。手探りで経験値を高めております。で、よく見ると、CSVファイルは 4データを用意したのに3データしか出ていない。はてな?

これは、きっと1行目をヘッダーと看做して、スキップしたに違いない。これも経験値だな。 githubにサンプルが出てて、それを覗いたら、らしいのが出てた。

    let fp = &Path::new("./2015.csv");
    let mut rdr = csv::Reader::from_file(fp).has_headers(false);

ヘッダーを持ってるか?って質問を追加して、それにNoと答えると、1行目もデータとして 扱って(表示して)くれるようになった。デフォではヘッダー付きって、EXCELからの データを扱い易くしてるんだな。Windows寄りの設定で、世界のWindowsユーザーを取り込もうと 言う作戦。

そう言えば、上で出てきた、cargoのための設定ファイル、Cargo.tomlもWindowsの設定 ファイル、xxx.iniにそこはかとなく似てるな。これもWindowsユーザーの敷居を下げる 効果が有るんでしょうか?

最初、dependencies を、後ろの方に書いたら、書式が違うぜーーってエラーを喰らった。 そんなの知らんわってんで、 TOMLとかの文法を 見たんだ。YAMLとかJSONとかに喧嘩売って、車輪の再発明してる。そして、この最、MAC なんて抹殺しちゃえって事で、MAC用の行末文字 CR は、無視してますよ。怒れよ、MAC ユーザー!!

使える行末コードは、linux用のLFと、Windows用のCRLFだけですってさ。この際Windows屋に 文句を言っておきたい。(正確にはDOS屋だから、ゲイツ野郎にだけど) どうせマネするなら、行末コードもUnix合わせて、LFにしとけば良かったの。

で、ゲイツからの反論。そんな事言ったって、あの頃使えた電動タイプライターは、 テレタイプ社のASR33だけしかなかったの。その改行シーケンスを見てると、フォントを 掲載したプリントヘッド(キャリッジとも言う)が左端に復帰。次に1行分の紙送りって具合に2動作になってたの。 それをそのまま、文字コードに当てはめたら、CRLFになった訳よ。何か文句ある?

Unixの端末ドライバーみたいに、裏でこそこそさせるの嫌いなのよね。そもそも、 端末ドライバーなんて言う魔窟な事は考えなかったの! だって、パソコンの限られた メモリー上で動かすんだから。

で、後から出てきたアプル野郎は、Unixの行末やWindowsの行末文字に合わせるのも 癪に障る。そうすると残ってる文字はCRだな、って事で対抗した訳ですよ。

権力争いですなあ。TOMLフォーマットでMACを切り捨てたのは、政治的理由です。 Javascriptの正式名称は、ECMAScriptとか言うらしいけど、最初のEはEUのEですって 事で、ヨーロッパだよって主張してる。新大陸の分家野郎なんてエバルなよって訳。 規格なんてのは、名誉、勢力争い、利権、政治の産物さ。

cargo回り

tomlに関係して、cargoについても、ちょい調べた。Cargo.lockなんてのが自動で 作られる。どんな内容?

[sakae@fedora bld]$ cat Cargo.lock
[root]
name = "bld"
version = "0.0.1"
dependencies = [
 "csv 0.12.10 (registry+https://github.com/rust-lang/crates.io-index)",
 "rustc-serialize 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "csv"
version = "0.12.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "rustc-serialize 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "rustc-serialize"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"

ふむ、依存関係と、外部に有るファイルの取り寄せ方法を格納してんだな。なんか、rootって 根が有るんだけど。。。それらは、 Rustのクレイトとモジュールのガイド に、説明が有った。

言語を使うって事は、その言語の仕様とライブラリィの豊富さとcargoみたいな支援ツールの セットで考えておかんとな。

cargoの隠しディレクトリィーとして、.cargoが出来ていた。

[sakae@fedora ~]$ tree -d -L 4 .cargo 
.cargo
└── registry
    ├── cache
    │   └── github.com-1285ae84e5963aae
    ├── index
    │   └── github.com-1285ae84e5963aae
    │       ├── 1
    │       ├── 2
    │       ├── 3
    │       ├── ab
     :
    └── src
        └── github.com-1285ae84e5963aae
            ├── csv-0.12.10
            └── rustc-serialize-0.2.9

githubからのソースも保持してて、goと似てるな。indexの中身は何だろう? ひょっとしてcargoに登録されているライブラリィのDBかな?

[sakae@fedora github.com-1285ae84e5963aae]$ find . -name '*csv*'
./3/c/csv
./si/mp/simple_csv
[sakae@fedora github.com-1285ae84e5963aae]$ cat ./3/c/csv
  :
{"name":"csv","vers":"0.12.10",
   "deps":[{"name":"rustc-serialize","req":"*","features":[""],
      "optional":false,"default_features":true,"target":null,"kind":"normal"},
      {"name":"regex","req":"*","features":[""],"optional":false,
         "default_features":true,"target":null,"kind":"dev"}],
  "cksum":"e996628459d1478b5246c9c87100e700cfd544ea8f337a7476b16849ca9671ec",
  "features":{},"yanked":false}

ふーん、なるほどね。fedoraとかFreeBSDとかのpkgDBは、sqlite3の人間が容易に読めない フォーマットになってたけど、こりゃjson風に、人に優しい仕様にしてるのね。

それにしても、1,2,3,ab とかのdirは何や? 10秒考えたら、hashの一種と気がついた。 ライブラリィー名が、それぞれ、1文字、2文字、3文字とそれ以上に分けてる。それ以上は、 4文字以上って事だけど、それは、先頭から2文字づつのdir名にしてるんだ。

hogefooなら、ho/ge/hogefoo って具合になる。ここまで分かれば、現在幾つの貢献が 登録されてるか、簡単に調べられるな。

[sakae@fedora github.com-1285ae84e5963aae]$ find . -type f | wc -l
1320

まだ、本体はアルファー状態と言うのに、おまえら、よってたかって、好きでんなあ! それは、cargoの面々が貢献を推奨してるからです。アルファベット順に見てくのの他に 人気DL順でも検索出来て、gcc,rustc-serialize,pkg-config,regex,time,log あたりが、 1万回を超えてDLされてますよ。さあ、今がチャンスですよ。

そう言えば、ぐぐる様がhtmlのやり取りを効率化するためバイナリーフォーマットに しようよなんて事を言ってたけど、おまいら、インターネットの流儀を崩そうと言う んかい。人が容易に読めてこそのものだろうに! 邪悪になるなよ、M$みたいに。

rust-gdb

もう一つ気になってたやつが有ったな。そう、rust-gdb。早速使ってみよう。

[sakae@fedora bld]$ rust-gdb target/bld
GNU gdb (GDB) Fedora 7.8.2-38.fc21
  :
(gdb) b 21
Breakpoint 1 at 0x4426: /home/sakae/rust/bld/src/main.rs:21. (2 locations)
(gdb) run
Starting program: /home/sakae/rust/bld/target/bld
Missing separate debuginfos, use: debuginfo-install glibc-2.20-7.fc21.i686
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/libthread_db.so.1".

Breakpoint 1, bld::main () at src/main.rs:21
21              println!("({}, {}): {}", record.s1, record.s2, record.dist);
Missing separate debuginfos, use: debuginfo-install libgcc-4.9.2-1.fc21.i686
(gdb) c
Continuing.

Breakpoint 1, bld::main () at src/main.rs:21
21              println!("({}, {}): {}", record.s1, record.s2, record.dist);
(gdb) print record
$1 = Record = {s1 = String = {vec = Vec<u8> = {ptr = NonZero<*mut u8> = {
        0xb741b020 "15010104130"}, len = 8, cap = 8}}, s2 = String = {
    vec = Vec<u8> = {ptr = NonZero<*mut u8> = {0xb741b030 "130"}, len = 3,
      cap = 3}}, dist = 73}
(gdb) c
Continuing.
(15010104, 130): 73

綺麗にrecordデータを表示してくれると思ったんだけど、何これ? 醜態を晒しているよ。 本当に綺麗表示ルーチンがインストールされてるんだろうね?

(gdb) info pretty-printer
global pretty-printers:
  builtin
    mpx_bound128
  objfile /home/sakae/rust/bld/target/bld pretty-printers:
  rust_pretty_printer_lookup_function

一応よさそう。更に、どんなコマンドでgdbが起動されてるか見とくと

/bin/sh /usr/local/bin/rust-gdb target/bld
gdb -d /usr/local/lib/rustlib/etc -iex add-auto-load-safe-path /usr/local/lib/rustlib/etc target/bld

一応、よさそう。そうすると、gdb自身がpython連携出来ていないの? やおら、その辺を探ってみると、 Python Pretty-Printer なんていうのが出てきた。ちょっとコピペして実行してみると

(gdb) print myFruit
$2 = {fruit = 1}
(gdb) python execfile("fruit.py")
(gdb) print myFruit
$3 = Our fruit is Apple

ちゃんと実行してる。これはもう、要保護観察処分だな。ほとぼりが醒めたら、また 引っ張り出してみよう。それまでは、gdbが自前で持ってる、綺麗表示で我慢しよう。

(gdb) p record
$1 = Record = {s1 = String = {vec = Vec<u8> = {ptr = NonZero<*mut u8> = {
        0xb741b020 "15010104130"}, len = 8, cap = 8}}, s2 = String = {
    vec = Vec<u8> = {ptr = NonZero<*mut u8> = {0xb741b030 "130"}, len = 3,
      cap = 3}}, dist = 73}
(gdb) set print pretty on
(gdb) p record
$2 = Record = {
  s1 = String = {
    vec = Vec<u8> = {
      ptr = NonZero<*mut u8> = {0xb741b020 "15010104130"},
      len = 8,
      cap = 8
    }
  },
  s2 = String = {
    vec = Vec<u8> = {
      ptr = NonZero<*mut u8> = {0xb741b030 "130"},
      len = 3,
      cap = 3
    }
  },
  dist = 73
}

rust-runでエラーた

試運転を終わって、さあコードを書くぞってんで、emacsに行った。そこで、オイラーが 作った rust-runを実行すると

     Running `../target/bld`
thread '<main>' panicked at 'called `Result::unwrap()` on an `Err` value: could\
n't open path as file (no such file or directory (No such file or directory); p\
ath=2015.csv; mode=open; access=read)', /home/rustbuild/src/rust-buildbot/slave\
/nightly-dist-rustc-linux/build/src/libcore/result.rs:742
An unknown error occurred

Process rust-run exited abnormally with code 101

今までshell上で正しく実行出来ていたのが、この有様ですよ。でもエラーの内容を冷静に 見ると、2015.csvが無いと言ってる。

そして、実行してる階層が、target/bldのある所より一段低い。何でそうなるかは不明だけど、 深くは追求しないで、対象療法しとく。

    let fp = &Path::new("../2015.csv");
   Compiling bld v0.0.1 (file:///home/sakae/rust/bld)
     Running `../target/bld`
(15010104, 130): 73
(15010121, 120): 68
(15010205, 118): 73
(15010221, 101): 60

Process rust-run finished

昔、テンだかカンマを付け忘れて、ロケットが墜落したそうだけど、現代でもそんな事が 起こる、emacsの怪とでも言いましょうか。。。

んでもって、一体何処に居るんや? こういう時は、getwdだな。

use std::os;
 
    let current_working_directory = os::getcwd().unwrap();
    println!("Here is {:?}", current_working_directory.display());

こんなのを追加して、emacs上から実行すると

Here is "/home/sakae/rust/bld/src"

shell上からは、言うまでもなく

[sakae@fedora bld]$ cargo run
     Running `target/bld`
Here is "/home/sakae/rust/bld"

になりました。emacs src/main.rsで起動すると、emacs君は内部的に srcの下へ移動 するんだな。余計な事をやりやがって.. (以下略)

余計な事の回避は、getwdして、srcが含まれていたら、os::change_dir でもすれば いいんだな。それにしても、chdirじゃないのは、微妙な名前だな。(by unix user)

[sakae@fedora src]$ ln -s ../2015.csv 2015.csv

unix userを自称するなら、こうするのが正しい選択です。