CSVとかTSVをJSON LinesにするツールをGoとRustで書いた

CSVとかTSVをJSON LinesにするツールをGoとRustで書いた。

Go版

github.com

$ printf 'foo,bar\nbar,zoo' | xjsonl -keys a,b
{"a":"foo","b":"bar"}
{"a":"bar","b":"zoo"}

Rust版

github.com

$ 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 LanguageRust By Exampleを読んでいたのだけれど、いまいち頭に入らず。 最終的に「プログラミング言語Rust入門」という書籍をKindleで購入。

プログラミング言語Rust入門

プログラミング言語Rust入門

全部がカバーされているわけではないけれど(マクロの書き方とかアトリビュートの詳細とかジェネリクスの細かいところなどはなかった)、足がかりとしてはよい本だったと思う。

Rust版を作りながら思ったこと

  • unwrapまわりが最初わかりにくかった
    • https://qiita.com/nirasan/items/321e7cc42e0e0f238254 がとても参考になった
    • Goから入った人間としては「そんなにパニックしていいのか?」と思ったが、log.Fatalfを使ってたりするので、同じなのかも。unwrapよりはexpectでわかりやすいメッセージを表示した方が良さそうだけど
  • dbg!マクロは最初の方で知りたかった…
    • 参照にしないとたまにコンパイルエラーになったりするあたり、新鮮味を感じた
  • strとStringがあるのがややめんどくさい
    • とりあえずstructに併せてStringを標準的に使うようにしたけれど、正しいのかわからない
      • 引数は&strにしてみた
    • Stringのマクロかリテラルが欲しい
  • ファイル分けの標準がいまいちよくわからなかったので、Goっぽくはしてみた
    • モジュールまわりは解説を読むよりは https://github.com/shadowmint/rust-starter が参考になった
    • main.rsとlib.rsを共存させるよりはmain.rs内でmod hogehoge;と書いてしまった方が、CLIを作るときは楽なんじゃないかなーと思ったけれど、そういう例は見つからず…
    • →素直にlib.rsを書け、という気になってきた
  • ジェネリクスに慣れていないせいで、最初「キャストの方法は?」と探しまくった
  • クロージャがやや使いにくい気がした。定義ごとに個別の型になっているせい?なんとなく、引数で受け取るときはfn()使うよりもFn()を使っておいた方が無難な気がした
    • Golangのノリで、関数を返す高階関数を書こうと思ったけれど、めんどくさい感じになったので諦め。結局、関数ポインタを多めに使うようにした
    • クロージャに限らず、戻り値でのジェネリクスは鬼門感がある
  • テストはモジュール内で定義されていたほうがきれいな気がしたので https://github.com/winebarrel/xjr/tree/master/src/xjr のようにしてみたが、いいのか悪いのかわからず
    • mod.rsに実装書くのはアリなのかな?
  • ロスコンパイルはcrossでサクッとできた
  • splitにややはまった
    • "".split(",") -> ""
    • Rubyが特殊な仕様なのかも
  • trim_rightがdeprecatedでこだわりを感じるなど
  • Goに比べると実行ファイルがとても小さいのでよかった
  • 所有権については難しそうなイメージの割にほとんど考えることはなかった
  • ネストが深くなりがちなのはmatchのせいだろうか?
    • xjrは見直してみるとなんかGoっぽいかんじになってしまった

その他、Rustで参考にしたサイト

Rust所感

  • 個人で書いている分にはとても楽しい。よい言い方ではないけれど、パズル的な楽しみがある
  • プロジェクトで採用するには結構決断力がいりそう。慣れているか高スキルのメンバーが多くない限り、Golang選びそう
    • Goは手の筋力が必要だけど、Rustは脳の筋力が必要な感じ
  • Golangはランタイムの豪華さがやはり最大のメリットだなーと思った。ただ、今回は並行プログラミングまわりを全然比べられていないので、その辺は別途深追い予定
    • 関係ないけど、vlangはランタイムをがんばらないとGoほどのメリットは感じられなさそうな気がした