TaPL読書録 #4

前回:

hkdnet.hatenablog.com

今回は5章終わりまで、と思っていたが 5.2. の最後まででいい時間になってしまったので終わり。

今回は記憶がおぼろげなのでおぼろげに書きます。

ラムダ計算におけるリストの表現などについて Scott encoding, Church encoding と言われて何もわからなかったが、以下のブログに詳しい。

d.hatena.ne.jp

ラムダ計算ができる言語が欲しくなるが、arrow function があるJavaScriptがよろしいのではないかという話になった

github.com

power の話になったときに、回答例の power2 がこれは確かに power であるという確信がもてない。ここで power2' について考える。

power2  = \n. \m. m n;
power2' = \n. \m. \s. \z. m n s z; # イータ変換による

型のようなナニカを雰囲気で想像したときに(要は定義をせずに使う)。
まず Church数 は2引数関数であり、第一引数に a -> a な関数を、第二引数に a を取り、a を返します。

cn :: (a -> a) -> a -> a

ここで m n に注目すると m :: (a -> a) -> a -> an :: (a -> a) -> a -> a について、 A = (a -> a) とすると n :: A -> A と捉えることも可能で型が一致しているような雰囲気があって面白い。

m :: (A -> A) -> A -> A
m :: ((a->a) -> (a -> a)) -> (a -> a) -> (a -> a) # 展開した
m n :: (a -> a) -> (a -> a) # nを適用した
m n :: (a -> a) -> a -> a # カリー化を考えると括弧に意味がない気がするので消した

となり m n が Church 数の型と一致するのが確認できる。

さて、我々は plus を手に入れ times を手に入れ power を手に入れるに至った。そうすると Knuth の矢印表記についても考えたくなるのは必然であるという話になった。ので、軟弱な私は即座にググった。

mindsarentmagic.org

やっぱりあったね。相性いいね、という気持ちになって終わった。

equal について、回答例では再帰を使わなかったが以下のようにも書けるような気がする。

eq = \m. \n. test (iszro m) (iszro n) (eq (prd m) (prd n));
eq = \m. \n. test (or (iszro m) (iszro n)) (and (iszro n) (iszro m)) (eq (prd m) (prd n))
2引数をとる関数に対応するYコンビネータ G に関して
equal = G eq

ここで教えてもらったのが、不動点コンビネータを使わずに関数を引数にとる方法もある。 lambda計算においては、適用するときに同じ項をそこに平べったく書けば良いとのこと(未検証)

fact f c = if (iszro c) then (succ 0) else (f f (prd c))
showFact = fact (if (iszro c) then (succ 0) else (f f (prd c))) c4

次回は5.3 〜 6章全体まで。

『わかばちゃんと学ぶ Googleアナリティクス』の献本をいただきました

f:id:hkdnet:20180422143933j:plain

はいどうも、 ハイクオリティ神レビューア のはくどーです。
頂いたの3月末なのですが……。遅くなりましてすみません。

感想

ざっくりGAの使い方が紹介されていてよいんじゃないでしょうか。アクセス解析にまつわる諸概念についてもざっと紹介され、各概念を混同しないように説明しようという意思を感じました。
また、いつもの湊川節で「どうしてそれやるんだっけ?」「それってほんとにちゃんと目標に沿ってるんですか?」と優しく詰められるのが心地よかったです。

経緯

Twitterすごい(こなみかん

ふりかえり

実際にやってたこと

GitHub ベースでのレビューでした。
レポジトリが用意されて、markdown原稿がPRでとんでくるのでレビュー。
おそらくレビューが終わったあとに出版社の人が組版してくれて本になっている。
僕がレビューしてる段階ではあくまで markdown ( + そこから生成されるHTML )が対象。

よかった

  • 対象ドメインがわからないので最初の読者として質問しまくれた
    • 結果、わかりにくい点が減ったと思う
  • はじめて用語の統一などを意識して文章を構築する経験ができた
    • ふだんは適当なので……
  • 文章だけでなく、マンガ・イラスト部分にまで足を伸ばせた

わるかった

  • PRが巨大になりがちで難しい
    • chapter 単位でのPRになっていたのだけど、分量が多い
  • 修正が妥当かどうかを確認するのが難しかった
    • 特になんどもすり合わせをしているようなとき、outdated な変更と見比べるのが難しかった
  • GitHub の diff viewer で画像が見れないのがめんどい
  • うまく違和感が言葉にできないことがあった
    • なんかよくわからないんだけどこの言い回し変な気がするんだけど俺の語彙力がないせいなのかはたして、みたいなやつ
    • いつもの仕事だったら適当に対面で話すんだけどどうしたもんか

次あったらどうしようか

  • 問題: PRが巨大になりがち
    • 解決策: chapter 単位ではなく section 単位でPRにする
      • 懸念: 用語の統一とか section 間での流れの悪さに気づけるか?
      • feature ブランチで chapter を作って各 section を feature 向けのPRとする、とよさそう
      • 今回はこういうブランチ運用とかまでちゃんと話せなかったなーという追加反省
  • 問題: 修正が妥当かわかりにくい
    • 解決策: PRブランチへのPRで修正を反映する
      • 懸念: ちょっとめんどくさいかも

2018年04月24日 00:25頃追記 図を書きました

f:id:hkdnet:20180424002556j:plain

草活1周年、に失敗した話

f:id:hkdnet:20180422141206p:plain

3/31なんですけど、とあるレポジトリにコミットしてたのが、とある事情によりレポジトリごと消えたので草も一緒に消えてしまいましたとさ……。

これ private repo のも含めていて(= 会社のも含んでいる)、OSSっぽいことをしているわけではないのでアレなんですけどね。
達成したら記念に日記書こうと思ってたのだけど達成できなかった記念に置いておきます。

『現場で役立つシステム設計の原則』感想

読んだ。

雑多に感想を書く。

いわゆる Rails Way において到達できるところと、実際にシステムが要求するところの水準に乖離があるような現場はそこそこあると思っていて、Rails から入ったけどそういうところに困っている人(= つまり僕だ)にいい本だと思った。
ふだんなんとなく気にしていることが明文化されているのがよかった。

とりあえず本記事の読者層をRailsさわったことありますという人として、第8章(アプリケーション間の連携)以降はあまり読む必要はなさそうだった。本書のよさはそこにはなく、蛇足だと感じたが、それは普段どういった情報に触れているかという話でもあるので読む人によるのだろう。

たとえばいわゆる Rails Way の何が厳しいのか。それを語るには Rails 歴がたりなさすぎるのであるがそれはおいておくとして、1つの指摘として「REST表現におけるリソースとDBのテーブルが1対1に対応する」という素朴な前提がよく育ったアプリケーション(あるいは対象ドメインによっては)当てはまらないということがあると思う。

bin/rails g scaffold Post でうごいたわーいというのはプロトタイピングとして優秀であるのですが、たとえば post を作るのは1つのクチでいいのか、という話。
たとえば有料課金ユーザーにのみに許されるアフィリンク追加みたいな機能があるかもしれない、あるいは記事を「書く」のではなくツイートの切り貼りで1つの記事を作りたいかもしれない。もしかしたら記事自体を売りたいというような要求が出てくるかも。こういった posts テーブルにまつわる種々の事柄1をどう捌いていけばいいのかというのが Rails Way を超えた先にあるような気がしている。

Rails Way 以外のナニカに触れる機会として本書は非常によかったように思う。いま対峙しているアプリケーションにおいてどう設計するのがよいか、Rails Way と違う点は何かを考えるための機会を得たという感触がある。


  1. posts 以外のテーブルに入れたほうがいいような例もあった気はしつつ

秒速でサイト作ったら反響がよかったので振り返り

github.com

きっかけは、隣に座ってた人がいきなりやり始めたんだけど、検索ロジックとかが ガバそう 改善の余地がありそうだったので口出ししてたところから。

やったことは主にこんな感じです。

  • (PRになってないけど) 検索ロジックに口出しした
    • とりあえず \s+ で分けて、それぞれに対してマッチするかでANDとればいいと思うよ、と話した
    • むかーし slack の検索を自前でやろうとしたときに似たようなことをした
    • そのときは単語の順番も考慮したいので new RegExp(str.split(/\s+/).join('.*')) みたいな感じだった
    • 当時も今もパフォーマンスは気にしない前提
  • bulma 導入
    • element-ui を使おうとしてたっぽいけど設定ミスって中国語になってた
    • だったらもう bulma 使おうぜと提案して勝手に導入
  • use strict した
  • IE11対応
    • arrow
    • オブジェクトのメソッド記法を直した
    • String.protoype.includes がないので String.prototype.indexOf で代用
    • IE だと死ぬほど検索遅いんだけどターゲット層はIEユーザーが多いとのこと。はい
  • placeholder 追加
  • {{}} が見えないように v-text を使用
  • favicon 追加
  • strong とかを bulma 化

最初のほうはやることたくさんあって楽しいですね。スタイルはまだまだ貧弱なのですがそこは苦手な分野なので PR をお待ちしております。

その rescue_from ほんとに必要ですか

だいたい必要ないと思ってますよ、という話。


Rails アプリケーションの開発において rescue_from を追加することが正しいことは少ないと思っています。
rescue_from とは実際にはアクションおよびコントローラをまたいだ begin - rescue ( try - catch )であると言えます。
begin - rescue は大きく分けて2種類の使い方があると思っています。1つは、局所的な例外処理を書くとき。もう1つが例外からの復帰を諦めた場合に最後に(最初に)囲んでおくやつです。
ここでは前者を「復帰用rescue」、後者を「覆い隠し用rescue」と呼びます1

class Foo
  def fetch
    AwesomeHTTP::Get("https://example.com")
  rescue AwesomeHTTP::Error => e # ライブラリのエラーを拾っておく
    # 「復帰用rescue」 ( 局所的な例外処理 )
    raise MyApp::APIError, e
  end
end

begin
  Foo.new.fetch
rescue MyApp::Error => e
  # 「覆い隠し用rescue」
  # 復帰できないときには MyApp::Error あるいはそのサブクラスを投げるという規約にしておく
  warn "エラーが発生しました"
  warn e
  exit 0
end

rescue_from はこの使い分けでいうと「覆い隠し用rescue」であると言えます。根拠は、どこで起きるかは関係なくすべて拾ってユーザー側には通知しないようにしている点です。

Rails にはある程度のエラー処理を自動的にやってくれる仕組みがあります。Rails guide の rescue_responses を参照してください。

Configuring Rails Applications — Ruby on Rails Guides

rescue_responses を使わずに rescue_from のブロックで何か動的に処理をしたくなっている時点で「復帰用rescue」に該当していると思います。
しかし、復帰時の方法は果たしてコントローラ単位で本当に共通なのでしょうか?どこで起きた例外かによって処理を変えたいのでは?

というわけで rescue_from を書いておいたほうがいいことってほっとんどないと思うんですけどどうなんですかね。 ただの500ページより情報量が多いエラーページを出すために ApplicationController に書いとく、とかはアリなのかなあ。


  1. よい名前、あるいはこれに該当する分け方が既にあったら教えてください :bow:

jewel polisher

最近自分たちのプロジェクトが依存する gem 関連で何かが起きて対応が必要だったことが続いたのでメモっておく。

rails-html-sanitizer 0.4.0

CVE-2018-3741 対応。これは依存が多いので追うのがちょっとめんどかった。情報としては以下の issue が非常によくまとまっていたので置いておく。

github.com

libxml2 <- nokogiri <- loofah <- rails-html-sanitizer という依存関係で、大本は libxml2 の脆弱性
属性に HTML コメントとして解釈できそうな文字列が含まれたときに適切にサニタイズしないことがあるように読めた。1

これはかなり前に報告済み2 だがlibxml2 では修正されてないっぽい? とりあえず loofah 側ではこれを対応できるようにpublic なメソッドをはやしてくれている。

https://github.com/flavorjones/loofah/commit/56e95a6696b1e17a242eb8ebbbab64d613c4f1fe

rails-html-sanitizer はそれを使うようにした、という感じ

https://github.com/rails/rails-html-sanitizer/commit/f3ba1a839a35f2ba7f941c15e239a1cb379d56ae

該当コミットで追加されたテストケースを対応前のバージョンで走らせたらこんなだった。

  def test_uri_escaping_of_href_attr_in_a_tag_in_white_list_sanitizer
    html = %{<a href='examp<!--" unsafeattr=foo()>-->le.com'>test</a>}

    text = white_list_sanitize(html)

    assert_equal %{<a href="examp<!--%22%20unsafeattr=foo()>-->le.com">test</a>}, text
  end

# -"<a href=\"examp<!--%22%20unsafeattr=foo()>-->le.com\">test</a>"
# +"<a href=\"examp<!--\" unsafeattr=foo()>-->le.com\">test</a>"

対応としては普通に update すればおk

mysql2 0.5.0 リリース

リリースされたのだが Rails5 で mysql のバージョンをうまく制限していないと以下のコードで死ぬ。

https://github.com/rails/rails/blob/a0c43ce39b6b2ff2cd8f7fee07f809f34cad9b5b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb#L4

gem "mysql2", ">= 0.3.18", "< 0.5"

普通にしてると mysql2@0.5.0 が入ってきて「バージョンを満たす gem がない」などのエラーになる

対応は簡単で mysql2 のバージョンを固定しておけばよい。Railsと同様に "< 0.5" をつけておけばよいだろう。

現在の stable の先っちょでは対応済みっぽい3github.com

0.5.0 対応して大丈夫か、という判断があるので 5-1-stable ではバージョン指定で対応するかと思ったけど普通にゆるめてくれましたね。ありがたや。


普段自分の仕事内容を思い出そうとしても、こういう活動は忘れがちなので残しておいた。
アプリケーションというのは、機能を追加すれば複雑性が増すし、何もしなくても部品のメンテが必要である。
Rails バージョンアップなどの目立つものもあるが、目立たないこういったところで追随する努力も必要であるし意味のある仕事なんだぞと自戒をこめて書いておく。


  1. 同僚は https://github.com/GNOME/libxml2/blob/960f0e275616cadc29671a218d7fb9b69eb35588/HTMLtree.c#L714-L718 から a タグの href, action, src, name 属性のみかな?と言っていたが検証していない

  2. 2016-08-11 18:29 とのこと。 https://bugzilla.gnome.org/show_bug.cgi?id=769760 をみると “Can I ask again that the libxml2 maintainers consider addressing this issue?” などと言われているのが見える

  3. ライフサイクルよくわからんけど 5-0-stable には backport されてなくて気になる(のでコメントしている)