CSVとかTSVをJSON LinesにするツールをGoとRustで書いた。
Go版
$ printf 'foo,bar\nbar,zoo' | xjsonl -keys a,b {"a":"foo","b":"bar"} {"a":"bar","b":"zoo"}
Rust版
$ printf 'foo,bar\nbar,zoo' | xjr -k a,b {"a":"foo","b":"bar"} {"a":"bar","b":"zoo"}
モチベーションとか
qrnを作った関係でテキストをJSON Linesに変換するツールが欲しくなったのだが、あまり上記のようなツールが見つからず、joで頑張るのもめんどくさい、ということで自作した。
かなり小さいツールなので、Rust学習のためにポートするにはちょうどいいかと考えてRust版も作成。
Rust入門
The Rust Programming LanguageやRust By Exampleを読んでいたのだけれど、いまいち頭に入らず。 最終的に「プログラミング言語Rust入門」という書籍をKindleで購入。
全部がカバーされているわけではないけれど(マクロの書き方とかアトリビュートの詳細とかジェネリクスの細かいところなどはなかった)、足がかりとしてはよい本だったと思う。
Rust版を作りながら思ったこと
- unwrapまわりが最初わかりにくかった
- https://qiita.com/nirasan/items/321e7cc42e0e0f238254 がとても参考になった
- Goから入った人間としては「そんなにパニックしていいのか?」と思ったが、log.Fatalfを使ってたりするので、同じなのかも。unwrapよりはexpectでわかりやすいメッセージを表示した方が良さそうだけど
- dbg!マクロは最初の方で知りたかった…
- 参照にしないとたまにコンパイルエラーになったりするあたり、新鮮味を感じた
- strとStringがあるのがややめんどくさい
- とりあえずstructに併せてStringを標準的に使うようにしたけれど、正しいのかわからない
- 引数は&strにしてみた
- Stringのマクロかリテラルが欲しい
- とりあえずstructに併せてStringを標準的に使うようにしたけれど、正しいのかわからない
- ファイル分けの標準がいまいちよくわからなかったので、Goっぽくはしてみた
- モジュールまわりは解説を読むよりは https://github.com/shadowmint/rust-starter が参考になった
- main.rsとlib.rsを共存させるよりはmain.rs内で
mod hogehoge;
と書いてしまった方が、CLIを作るときは楽なんじゃないかなーと思ったけれど、そういう例は見つからず… - →素直にlib.rsを書け、という気になってきた
- ジェネリクスに慣れていないせいで、最初「キャストの方法は?」と探しまくった
- stdinとファイルを同じように扱うのに http://saba1024.hateblo.jp/entry/2017/12/20/011335 のような方法をとっていたけれど、ジェネリクス使った方がスマートなのかなーという感想
- なので方針としては「dyn潰すマン」
Box<dyn error::Error>
はジェネリクスでなんとかしようとしたけれど、できず。これはそのままでいいのかな?
- クロージャがやや使いにくい気がした。定義ごとに個別の型になっているせい?なんとなく、引数で受け取るときは
fn()
使うよりもFn()
を使っておいた方が無難な気がした - テストはモジュール内で定義されていたほうがきれいな気がしたので https://github.com/winebarrel/xjr/tree/master/src/xjr のようにしてみたが、いいのか悪いのかわからず
- mod.rsに実装書くのはアリなのかな?
- クロスコンパイルはcrossでサクッとできた
- splitにややはまった
"".split(",") -> ""
- Rubyが特殊な仕様なのかも
- trim_rightがdeprecatedでこだわりを感じるなど
- Goに比べると実行ファイルがとても小さいのでよかった
- 所有権については難しそうなイメージの割にほとんど考えることはなかった
- ネストが深くなりがちなのはmatchのせいだろうか?
- xjrは見直してみるとなんかGoっぽいかんじになってしまった
その他、Rustで参考にしたサイト
- cargo test で 標準出力をコンソールに流す - Qiita
- Rust の Fn, FnMut, FnOnce の使い分け – kanejaku.org
- Rustでエラーを合成する - Qiita
- Panic を恐れるべからず - 何とは言わない天然水飲みたさ
- 2019 年の非同期 Rust の動向調査 - Qiita
- Rustプロジェクトのディレクトリ構成 - Qiita
- (後で読む) Getting Started - Asynchronous Programming in Rust