Blog株式会社マネーフォワード公式開発者向けブログです。技術や開発手法、イベント登壇などを発信します。サービスに関するご質問は、各サービス窓口までご連絡ください。(2016年10月)こんにちは。ruby-coreというRuby本体の開発の議論がされているメーリングリストがあります。新機能やバグ報告などがだいたいここに集約されてくるので購読しておくとRubyの動きが分かります。最近興味深かったトピックを紹介します。BigDecimal#infinite?以前も紹介したかと思いますが、Float以外の数値的なやつにもfinite?といったメソッドが追加になりました。統一的に扱えるようになります。Net::HTTP.new環境変数でno_proxyというものがあるわけです。これはなにかというと、設置環境がproxyを経由しないと外に出て行けないため、proxyを設定しているけれど、とはいえローカルのたとえば192.168.0.1とかにそれはそれでイントラネットのサーバが動いていて、それにアクセスするためにはproxyにアクセスしてはいけないとかいうケースです。いうときのために「(普段はproxyを使うけど)このホストにはproxyを使わないでほしい」という一覧を指定できる。これは別にrubyだけじゃなくて、一般的に使われているものです。なんとなく空気でそうなってるのか、それとも明確な規格があるのかよくわからないですが、少なくとも1995年時点でMosaicは実装してるぽい文献がヒットするので20年以上の歴史はあるぽい。環境変数を解釈するのそれはそれとして、とはいえ環境変数はグローバルだから、Rubyスクリプトの内部からはなかなか扱いづらいものがあるわけですよ。書き換えようとすると副作用が予測できないから、かなり面倒。本件の要求のようにコネクション単位で指定できるようになっていると嬉しいというのは理解できなくもない。問題は、Net::HTTPというのはHTTPをハンドリングする中では一番低層、セッション層の直上のレイヤーなわけです。本来はNet::HTTPというのはさらに上位層のライブラリがそういうno_proxyとかそういうのは適切に解釈した後に実際にTCPとかSSLとかのセッションを開きに行くところという設計なわけ。no_proxyみたいなのを置くには適切な場所ではない。低層をリッチにしてもろくなことがないし。いうとそれもなんか違う(標準で実装されるべき機能ではある)し、あんまりどこに置けばいいかというのがよくわからんという現状ですね。CPU.さまざまなところでinspectというメソッドが呼ばれることがありますね。このメソッドはオブジェクトを文字列に変換するんだけど、オブジェクト同士の参照をたどって全部文字列にしようとするから、複雑なネットワークを構成している場合にすごく大きな文字列になることがあります。一応、ネットワークのループは検出しているから、無限に長い文字列になることはないんだけど、DAGになっているときに強烈な感じになることがあって、何百万文字も生成するからプロセスが何秒も戻って来ないとかいうことになる。いえ、inspectが使われる時といえば、たとえば例外のメッセージの中で表示するとか、そういうやつでしょ。だいたいは人間が読む前提があるわけですけど、じゃあそんな何百万文字も生成された出力をまともに読めるのかという。このチケットで言われている問題意識は上記のような話ですが、人間が読むという意味では他にもinspectには何件か問題が指摘されていて、たとえば文字列がぶっ壊れてる時にぶっ壊れたままだと困るので適当にエスケープする機能があるんですけども、とはいえたとえば壊れてるんじゃなくて漢字とかならエスケープせずにそのまま表示してほしいじゃないですか。そのあたりの処理が、いまだとグローバルな設定など参照しつつマジカルな感じに動くんだけども、やはり本当はきちんと出力先エンコーディングを指定できるべきで、しかし指定できない、とか。的なAPIシグネチャになってるのがそもそも間違ってたということができて、たとえば設定を渡せないといけないとか、出力先のバッファを持ち回れば中間文字列の生成が抑制できるのに、とか、そういうのが様々に足りていないというのが、本来解決すべき問題ではないかという話になっているわけです。そこまで行くとかなり話が大きいため、なかなか手が動かないというのが問題。endendこういうやつ。問題は、「某方法名字」に適切な名前を誰も思い浮かぶことができてないという件なわけですね。本当に色々な提案がされているけれど、どれもしっくりこない。これに限らず設計というのは名前が決まればだいたい終わったようなものなわけですけれど、この例は特に、あと名前だけ決まらなくて困っているというやつのうちでも典型です。今回はitselfという名前が提案されているわけですが、それだとなんか変換結果じゃなくて、変換前のオブジェクトが返ってきそうに感じてしまうので違和感があります。exceptionこれはどちらかというと、整数に変換できなかった時にnilになるto_iが欲しいという話です。"foo".to_iとかが0を返します。的なシグネチャになっているという以上の理由ではないのだけれども、とはいえなんか無理矢理変換されている感は否めない。他に変換はないのかというと表題にあるようにInteger()というのがあって、これだと変換できなかったら例外になるわけです。例外というのもそれはそれで話が大きくて、もうちょっと手軽になってほしい。的なシグネチャになっているやつがほしいという話ですね。それを実現するのにIntegerを拡張するのがいいかどうかは議論のあるところかと思います。別建てにしてもいいのでは。addressingこのHashの内部構造を変える話、そろそろ入れるって毎回書いてるけど入らないですね。usedSymlinkごしのファイルを読み込もうとした時にrequireとrequire_relativeでSymlinkを解決するかしないかが違っていて、同じファイルが二回読まれてしまうことがあるので、困るという報告です。それ自体は、バグだとは思うし、修正すべきということ自体には異論がある人はいないとおもう。requireがSymlinkを解決しないのは意図的なんですよね。'active_support/core_ext/hash'だの本当に山のように呼ばれるので、初回ファイル読むのはしゃあないとしても二回目以降の呼び出しでも毎度readlink(2)呼びまくってると都度ディスクアクセスが走ってたいへん非常に辛くなっちゃうんです。requireは二回目以降はディスクアクセスが完全に回避されるようになっている。一方でrequire_relativeは「relativeとは何か?」というのを解決するところで自動的にディスクアクセスは不可避だし、jsonとかそういうのみたいに「わからんけどとりあえずrequireしとくか」みたいな使い方でもないので、こちらは問題なく解決されているわけです。ここに違いが生じている。いうわけで理由はそうなんですが、さておきバグはバグだと思うんで改修すべきですがどういう方向で解決すべきかよくわからない。一応、「Symlink解決したやつとしないやつと両方$LOADED_FEATURESに突っ込んどけば」という提案はあるんですが、それは逆にスクリプトからunloadしたくなったときに殺しきれなくなって困るという反論が出ていて、まあたしかになあという感じです。StringRuby初心者FAQでgsubの第二引数に$1とか使っちゃって動かなくて「第二引数じゃなくてブロックにしましょう」というのは鉄板中の鉄板ですね。$1というのはPerl由来のなぞの振る舞いをする特殊変数で、なぞなので、なぞなことになる。gsubをラップして俺函数を作ろうとすると、これはうまくいかないわけです。nil:NilClassまあようはPerl由来のなぞな振る舞いが、設計当初として便利だったのは否定しないんだけど、さすがにもはやRubyとPerlは別物なので。いまどきのRubyの用途にはあんましフィットしてないわけですよ。いうわけで$1とかに依存しないように、ブロックに明示的にMatchDataを渡せばいいよねという提案なわけですけれども。それで解決するといえば解決するわけですが、さりとてAPIが変わってしまうので、gsubという、マイナーと言ってしまうにはあまりに使われまくってるAPIに変更を入れるというのは、のきなみに動かないスクリプトばかりになることがあからさまに見えてるから、そこをどうするかで悩ましいという感じです。一応、方向性としては、別名の新しいメソッドを作りましょうという提案と、既存のブロックパラメーターはそのままで追加のパラメーターを増やせばいいじゃんという提案がいまのところ有力ですが、どちらも一長一短だねというコメントがついていて、決め手に欠ける感じになっています。libruby-static.a?ついに.aファイルがインストールされないことになってしまいました。プロジェクトが始まった頃にはまだ動的リンクという考え方自体の勃興期で、すべてのファイルが静的にリンクされている状態だったわけですけれども、その後いったん、.soなら.soで.aなら.aのどちらかを作るようになった(いつかわからんけど98年くらいの頃か?)後、2002年ごろに[ruby-dev:18700]で.soと.aの2種類のライブラリを作るようになって、長くその状態だったわけですが、でもまあ今時は動的リンクは当たり前だし、そうなってくると両方あるのは無駄というのは、まあそうかもしれませんが、とはいえ時代の変遷ですよね。十数年を経て20世紀の挙動に戻ったという。--disable-install-static-libraryとすることでこの古くて新しい挙動を試せるようになっています。issuesの多さが物語っている)、もちろんMac側を変えたら壊れるのがRubyのせいのはずはないんですよね。ところが事態はさらにひどくて、時を同じくしてPythonにも同様の報告がされているんですがそちらにて解析されている内容によると、どうやらAppleはSQLiteに勝手にGCD対応のパッチを入れていて、それのせいでSQLiteが壊れているんだそうで。SQLiteのせいですらなかった。いうわけでOSにバンドルされてるやつを窓から投げ捨てて各自で公式から取ってくるのが正解らしい。SQLiteもRuby(もPython)も公式同士で組み合わせればちゃんと動くという現状ですので、そのようにしてください。strings今回ppの出力が変わりました。これまで文字列はppしても横に長くべったり出力されていましたが、今回文字列に改行が入っていたらそこで分割されるようになりました。まあppの出力は人間が見る用なので、読みやすくなるのはいいことなんじゃないでしょうか。systemに入ってるほうの/usr/lib/libssl.soをリンクしちゃってへんなことになる、という挙動があるらしいです。インストールするから、普通に入れると普通にはまる事態になっているということのようですね。selfの名前を考えてくれるエンジニアを募集しています。ご応募お待ちしています。読者になるこのブログについてはてなブログをはじめよう!moneyforwardDevさんは、はてなブログを使っています。ブログを報告する引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。