rust-bindgenのupstreamが変わった

cargo:bindgenのupstreamがYamakaky/rust-bindgenからservo/rust-bindgenに変わった。変わった結果どうなったかというと、C++のヘッダのパース機能が大幅に改善したりする。

rust-bindgenを知らなかった人に簡単に解説しておくと、clangを使ってC/C++のヘッダをパースして、それを元にRustのC FFI binding用途のglue codeを生成するcrateのこと。

元々rust-bindgenはRust ProjectではなくJyun-Yan Youが始めたらしい。らしいというのは「git logを辿った限りだとそうなっている」以上のことを言えないから。その後、メンテナー間での移譲があったのかどうかはよくわからないが、2015年末の時点ではYamakaky/rust-bindgenがupstreamとなっていた記憶がある。自信ないけど。

Mozillastylo(Quantum CSS)をやる関係でC++で書かれたGeckoとのglue codeを作る必要が出て、2015年の後半ぐらいからservo/rust-bindgenとしてforkしてMozillaのpaid staffが用が足りるようになるまでコードを書いていた(今も続いている)。元々のbindgenはC++サポートはそんなに強く無かったと記憶しているけど、Mozilla側で手を突っ込みまくった結果として改善され、たとえばleveldbのC++ヘッダが丸々パース可能だったりする(実体験)。

で、merge into upstream! · Issue #21 · servo/rust-bindgenというissueが立っていて、色々あったんだけど、最終的にservo側がupstreamを引き継ぐことになった。

RFC 1774で2017年のターゲットの一つにC/C++との相互運用を挙げているし、Servoがupstreamを引き継ぐのは間違っていないのではないかな。RFCを考えるとrust-lang-nurseryが引き継ぐのが一番いいけれども、Rust Project最大のパトロンであるMozillaの一門であるServo Projectの下に置いておくのは妥当なように思う。

生成されるコードは何も指定しないと大きい。依存先を含めてシンボルを再帰的に変換していくので当然といえば当然である。 実用上はpublic apiだけを変換対象のホワイトリストに指定することのほうが多いと思う。なんとか-sysを作るための道具なので、そこで生成したコードをそのままアプリケーションコードから呼ぶべきではない。

使い方?それはREADMEでも読めばいいんじゃないかな。

2016年やったこと

本業

  • 色々あった
  • 2016年も大変な一年だった

前半

後半

github:voyagegroup/eslint-config-fluct

  • internalに使ってるルールを、そのままpublicにした感じ
  • npm公開とかは検討中. 別にnpm publishしなくても再利用できるしね.

Open Source Development

facebook/react

ReactiveX/rxjs

rxjsのpull requestはrebaseが必要だとnetflixのメンテナーが適当にcherry-pickしてmasterにlandするので、ちゃんと取り込まれたものでも、closedとmergeが両方あったりする

Microsoft/TypeScript

karen-irc/option-t

  • 細々と必要に応じて更新してたり

karen-irc/karen

  • 趣味プロジェクト
  • 完全に自分用のビルド設定遊び場と化している……

servo/servo

  • 今年も殆どinactive(何やったか忘れたほどに……)
    • mailing listとかissueとかpull requestはだいたい見てるんで、何やってるかは知ってるんですが……
  • ちょっと手が空いた時に簡単なpatchを気晴らしに送る、みたいな関わり方だった.
  • もう少しやりたかったけど、そこまでの精神的余裕がなかった

総評

  • 色々あった
  • 何かを新しく学んだ、という印象は少ない一年だった
    • なんかアウトプットだけで終わった感はあるんだけど、その割にインパクトのあるアウトプット思ったよりも少ないですね……
  • 2017年は、インプットとアウトプットをもう少し増やしたい

備忘録: yarnpkgで依存パッケージのガーデニング作業を楽に行う

前提

How to

  1. yarn outdatedとかで更新が必要そうなものを眺める
    • いきなり2へすっ飛んでもいい
    • バージョンをstableとかdevとかnextで指定している場合は出てきたり出てこなかったりするけど
  2. yarn upgrade-interactiveする
    • バージョンをstableとかdevとかnextで指定している場合は出てきたり出てこなかったりするけど
  3. 2を繰り返す
  4. yarn upgradeで, 表に出てこない依存関係含めてyarn.lockを更新する
    • 今のところ, ./node_modules/を消して, yarn.lockを消して, yarn installしてyarn.lockを再生成した場合と同じ効果が得られる

Node学園#23で広告ジャバスクリプトの話をしてきました

スライドに書いてない詳細とか補足とかは, 勤務先のブログに書くかもしれないけど, もう少し私的な記録として.

Node学園#23で, 今年の始め〜夏ぐらいにやっていた話をしてきた 元々, 東京Node学園祭2016にCFP出してたんだけど, 甲斐なく落選してしまったので, お焚きあげということで発表させてもらった.

コアの実装だけで言えば2週間ちょいくらいで片付けられたし, これ以外にも細々とした色々をやっていたので, 実働時間としては大して多くは無いんだけど, 精神的には今年で一番手間暇をかけたような感じだった. 実装が難しいというよりも, とにかく面倒くさい. 原理的に何が出来て何が出来ないのかを各種specを元にちゃんと詰めて実装する面倒臭さ.

そんな感じでなので, どこかの勉強会で発表して締めということにしてみた. 締めとして勉強会とかブログを一本まとめを出せるように仕事するのは結構楽しいというかチャレンジしやすくていいね. なるべくこういうスタイルで仕事をこなしていきたいものである.

オンライン広告については, テクノロジ的に面白いことが多いんだけど, Webのユーザーとして見た場合にクソみたいな広告案件と接することも多くて, 総体としてあんまり印象が良くないのが寂しいね. 仕方ないが.(編注: 個人の感想であり, 勤務先とは関係のない意見です).

そろそろJavaScriptは飽きてきたので, RustとかScalaとかJavaとかC#とかGoとかC++とか何かで新しい何かを書いていきたいものだが, はたまた.

東京Node学園#20でtry-catch使うなという話をしてきました

東京Node学園#20「Don't use try-catchというタイトルで話してきました。

option-tの話

最初は手前味噌なoption-tの話を主題にするつもりではあったんですが、そんなライブラリの話とかしたって特にトリッキーな実装をしているわけでなし、全然面白くないし、別に特定のライブラリを使わなくても実現できる内容なので、もう少し広めの話題ということでtry-catchを安易に使うのをやめようという話にしました。

宣伝がてらoption-tの話も入れていますが、option-tのREADME.mdにも書いている通り、これのみが正解というわけでもないし、TypeScriptなどの静的型付けな支援が無いと使いにくいこともままあるし、依存関係を増やす元になるので、無理して使う必要も無いでしょう。インスタンスメソッドを組み合わせて使うとか、そういったことに魅力感じる場合に、選択肢の一つとして選んでいただければ幸いです。

質疑応答

当日は質疑応答の時間が取れなかったので、懇親会で聞かれた内容について。

Promiseの型定義次第で解決されるのでは無いのか?

これについては、Twitterでも回答させていただいておりますが、私個人の認識としてはノーだと思います。

もちろん一定の緩和にはなりますが、Promiseコンストラクタに渡すexecutor内でのthrowに対してもPromise.prototype.catch(e)は動作してしまうので、type paramterを増やしても制約として機能しませんし、むしろ特殊化したE以外の値が実行時に飛んできた場合に各種制約の前提が崩れるので、全体としてはむしろ状況が悪化してしまいます。なので、ES6 Promiseのdesign上, catch()any型がわたってくるというTypeScriptの定義は正しく、これに基づいて対応策を考えるしかないのではないかと。

もちろん、ES6 Promiseとは異なるdesignになっているPromiseを使う場合は、この限りでは無いですが、そこまでしてcatch()でハンドリングしたいかというと、微妙かなーと。

なんかLintとかでbanできないの?

↑で。

ESLintの/*eslint-disable*/~/*eslint-enable*/の良いところは、限定解除の明示化すなわちRustlangのunsafeブロックなので、使いたい場合をopt-in化できるのは、まあアリなのでは無いかと思います。

バグは積極的にクラッシュさせて洗い出すほうがいいというけど、そうは言っても何でもかんでもバグはクラッシュって厳しくない?

厳しいケースもあると思います。

ただ、そういう要求がなされる場合(たとえソフトウェアのバグがあっても回復を試みなければならないシステムとか)、

  • 本当にエクストリームなアプリケーションは、そのような問題の解決についての研究などを元にしたdesignで構築されるべき
  • そうでないアプリケーションに関しては、だいたい殺したほうがいいが、それでも「もしかしたら死ぬかもしれない処理は別立てのプロセスで処理する」などのように、影響範囲を分割するなどして対処するべき
    • この手の非同期イベント駆動にしたほうがいい箇所こそNode.jsの強みでは。

ではないかと思います。 (そんなに詳しく無い分野なので、具体的にどの研究が良いなどの突っ込んだ話はできません……)

あと、そもそも何かしらのアプリケーションはリリース前にQAとかデバッグやるんだから、その期間に可能な限りバグを発見できるようにしたほうが良いというスタンスです。

これを守るとオブジェクトの生成とかで遅いケースってあるよね

あると思います。 ですが、全体・通常としては表現の明瞭さを重視するスタイルを取るべきで、ハイパフォーマンスを要求されるモジュール・アプリケーション・プロジェクトに関しては、それを重視した規約にする、というのが現実的ではないかと思います。

どうせ遅かったら究極的にはCとかアセンブラ書くしかないんだよ!

Joe Duffy - The Error Modelは読んで面白い?

読みたいと思ってるなら読んで損は無いと思う。 別に無理して読むほどじゃ無いけど、新卒の子とかには前半部分だけでも読ませたい

まとめ

大体こんな感じ

option-tにResult<T, E>型を実装した(簡易報告版)

概要

当該issue

github.com

使い方(v0.17時点)

CHANGELOG.mdの当該項目

ECMA262のIteration protocolsで遅延評価するIteratorを作る

これは何?

ECMA262 6th以降にはiteration protocols(と呼ぶべきもの)が導入されている、というのは皆さんもちろんご存知のとおりだと思います。これを使ってIterator<T>.next()が呼ばれるまでmap()などを実行しない(lazy evaluationする)Iteratorを作ってみようという話です。Rustのstd::iter::IteratorとかC#LINQとかが似たような挙動をしますよね。

今後、巨大なオブジェクトやリストに対してのIteratorが提供・出現した場合、毎回のように即時評価でfor-ofしたりArray.from()するなどは現実的ではないでしょう。以下のように書くことも出来ますが、

/**
 *  @template T, U
 *  @param {Iterable<T>} src
 *  @param {function(T):U} mapfn
 *  @return {Iterable<U>}
 */
function map(src, mapfn) {
  const iter = src[Symbol.iterator]();
  const next = function () {
    const { done, value } = iter.next();
    if (done) {
      return {
        done,
      };
    }
    const result = mapfn(value);
    return {
      done: false,
      value: result,
    };
  };

  return {
    [Symbol.iterator]() {
      return {
        next,
      }
    }
  };
}

const inifinityList = [...];
map(inifinityList);

bind operator proposalがacceptされないことにはa( b ( c() ) )のように書いていくケースの方が多くてダルい。俺はbind operatorの行く末を気にせずにArray.prototype.map()のようにメソッドチェーンで書いていきたいんだ、その気持ち、わかります。

というわけで、ものは試しにiterator protocolに則る形で実装してみましょう.

Proof Of Concept

型がややこしいのでTypeScriptで書いてみました。だいたいこんな感じ。どうせES6に型アノテーションつけた程度に書いてるので、適当にアノテーション落とせば動きます。

ちなみに基本設計はRxJS v5を元にしています。IterableとObservableでDualityだ! だからというわけではないですが、評価結果のキャッシュはopt-inになっています(cache())。安易にキャッシュしてしまうと、mapやfilterのコールバック関数がDate.now()などの副作用に依存している場合にバグってしまうので、明示的に使用する前提にしてます。

実用したい場合

大抵の場合は自分で再実装するか、Interactive Extensions (for JavaScript)あたりを待つか、新しい何かが出てくるのを待てば良いのではないでしょうか。

他にも、

などがありますが、2016年3月3日現在の安定版ではiteration protocolには対応してない模様ですが、今のところはES6~のIteratorが必須になるようなケースはそこまで多くはないと思っているので、これらを使うなどで凌ぐというのも現実的だと思います。