Functor における map の引数の順序を考えてたらいっこストンと腑に落ちた話

別に知見は書いてないですが、なるほどなーと思ったという感想を書いたエントリです。

ScalazとHaskellのFunctorの提供するmap(fmap)は、引数の順番が異なります。

  • Scalaz の Functor

    • def map[A, B](r: F[A])(f: A => B): F[B]
    • F[A] なFunctor値が最初の引数で、A => B な関数が次の引数で、F[B]なファンクター値が返り値
  • Haskell の Functor

    • fmap :: f => (a -> b) -> f a -> f b
    • (a -> b) な関数が最初の引数で、f a なファンクター値が次の引数で、f b なファンクター値が返り値。

つまり第一引数と第二引数が逆。

ふつうに考えると Scalaz のやつが直感的に思えます。C言語とかでも、ある構造体を操作するための関数って大体第一引数にその構造体を渡して、他のパラメータをその後に渡すし、Perlとかだって $nyan->do_something したら $nyan が第一引数に渡ってくるし。

なんでなんでそうなっているのか調べたわけではないんだけど、関数のリフティングするときにはHaskellみたいになってたほうが便利だよなーと思い当たって「ふーむなるほど」となりました。

要するに、Haskell スタイルだと f :: (a -> b) な関数を g :: (f a -> f b) に変換したいというときに、なにも特別なことをしなくても fmap f とすれば部分適応されるので自動的にそっから g :: (f a -> f b)を得ることができてうれしい。

一方 Scalaz はデータに注目した場合は直感的ではあるのだけれど、Liftingのためのメソッド lift の実装は def lift[A, B](f: A => B): F[A] => F[B] = map(_)(f) となっていて、引数の順番が違うせいで一枚噛ませる必要がある。

これ、言語の特徴を捉えていて面白いな、と思いました。つまり、Scalaオブジェクト指向的な考えで、第一の関心が「オブジェクト」の側にある。だから「最初にFunctor値を受け取って、それに対して関数を適用しますよ」という引数の順序のほうが自然なんだけど、liftみたいな"関数に主眼が置かれた操作"をやるときにScalazスタイルだと「引数の順番が逆だったらな〜」ってなる。

逆に、Haskellスタイルは第一の関心が「関数の側」にある。だから「関数をリフティングしたい」みたいなときは自然にかけるんだけど、データ(この例で言えば Functor値)のほうに注目していると、この引数の順序ってなんとなく不自然に思える。

で、思ったんですけど、これ、fmapに限らず、filterとかでもそうですね。Haskellはだいたい関数を第一引数に取るようになっていて、部分適応してやることによって新しい関数を作り出しやすいようになっている。

なるほどな〜〜〜という感じでした。

(さらに気づいたことを追記)

これ、型推論上の都合もありそう。型推論が左から右に流れるから、先にF[A]が来てないと、実際のFunctor値の型から A => B の A を推論してくれないという都合があるかもしれない。

肉をやりました

個人の日記です。

id:moznion がはるばる新潟まできて肉をやってくれるというので好意に甘えて肉をやりました。

f:id:nkgt_chkonk:20150307182338j:plain

肉をはじめたところです。すでに仕込み済の肉をmoznionが持ってきてくれたので、焼くフェーズから開始している様子です。

f:id:nkgt_chkonk:20150307182352j:plain

焼いてくれています

f:id:nkgt_chkonk:20150307182446j:plain

このような見た目で最高な感じでした

f:id:nkgt_chkonk:20150307182944j:plain

うまい(確信)

f:id:nkgt_chkonk:20150307183555j:plain

こちらはアンティクーチョというペルー料理だそうです。ハツをスパイスとかビネガーとかに漬け込んで焼いたものだそうです。これ本当においしかったのでうちでもやろうと思った。

f:id:nkgt_chkonk:20150307185037j:plain

牡蠣も食べたかったので生牡蠣をレモンと塩でいただきました。

f:id:nkgt_chkonk:20150307211718j:plain

今回の功労者が青色のなにかを口元に押し当てている様子です。

感想

肉はとにかくうまかったのでとてもよかったです。

昔から家にひとを呼ぶのは好きだったんですけど、息子が生まれてからはなかなかこういう機会を作ることができませんでした。でもやっぱり家にひとを呼びたくて、妻に相談したら快くOKしてくれて肉会開催の運びとなりました。今回は来てくれたひとたち(@moznion @hayajo @NPoi @sambaiz)がみんな息子の相手をしてくれて、息子もとても楽しそうにしていたので本当にみなさんありがとうございますという感じでした。

あとこういう遊びを理解してくれて協力までしてくれるししかもかわいいわたしの妻はまじで最高という感じなのでみなさんもわたしの妻と結婚するといいですよ。ぜったい渡さないけど。

ところで、ここからは自分語りです。

わたしが子どもの頃、実家では母が音楽教室をやっていたのですが、母がイベント好きなのもあって、我が家は様々なひとが訪れる場となっていました。いい年してけっこう人間としてダメな感じのギタリストのおじさんとか、民族楽器を作ったり叩いたり弾いたり作り方を教えるワークショップを全国旅しながらやってるドレッドのおじさんとか、そういうちょっと「変」なひとたちがよく家に訪れてました。

わたしはちょっと性格に難がある(ちょっとだと信じたい)ので、どうしても子供社会でうまくやっていくことができなくて、実際に小学校や中学校はかなり苦痛だったのですが、そういう様々なひとがわたしを可愛がってくれるというのが、とても救いでした。楽しそうに生きてる大人が「学校以外にも世界はあるんだぜ」ってその態度で教えてくれる子供時代で、それは本当に恵まれていたんだなぁ、と今では思っています。

だから、というわけではないですし、どっちかというと単純にわたしが遊びたいからなんですけど、今後も家に大人をガンガン呼んでいきたいなぁ。そして結果として息子が「楽しそうに遊んでる大人たち」の姿からなにかを感じ取ってくれたらそれは多分いいことなんじゃないかな、なんて思っています(まあまだ息子はわけわかってないと思うけどな!)。というわけで、今後も家にひとを呼びまくるんで友人各位は覚悟しておいてくださると幸いです!

テンプレートをDRYにするのは慎重にやったほうがいいですよねというお話

社内でレビューおじさん業してて書いた内容ですけど守秘する必要ない情報なんでちょっと内容書き換えてオープンアンドシェアーします。

本文

見た目とかUIというのはソフトウェアの中でめちゃめちゃ柔らかい部品(些細な変更されることが多い部品)なので、「同じような部品だから共通化しちゃおう」ってやると失敗することが多いです。

特に気をつけるべきなのは、たとえばコンテンツをランキング形式でテーブルで表示する画面と、新着から順にテーブルで表示する画面があって、このふたつのテーブル部分は一緒だからパーシャルにしちゃおう、みたいなやつです。

見た目とかUIというのはソフトウェアの中でめちゃめちゃ柔らかい部品、というのがここで効いてきて、「新着とランキングは基本的に同じ表示なんですけど、ランキングのほうではランクがアップしたかダウンしたかのアイコンを表示してほしいんですよね〜」とか言われたり、「今見てるページが新着かランキングかわかるように、こことこことこことここの色をページによって変えたいんだよね」とか言われたりすることは想像できますね。でもここでテンプレートがパーシャルになっちゃってたりすると、共通化したテンプレートにif type == :ranking みたいな分岐持たせることになったりしちゃいます。そうすると、それってもう共通化の意味ないよね〜状態になることが結構あります。

そんなわけで、テンプレートの共通化はかなり慎重にやったほうがいいと思います。「たまたま同じような表示であるのか」それとも「将来にわたって同じ表示なのか」っていうのはなかなかわかんないものですから。

じゃあどういうときにパーシャル使うべきかっていうと、複数ページで共有されるフッターとか、ウィジェット的なやつとか、グローバルヘッダーとか、そういう部分はどんどんパーシャルにしちゃえばいいと思います。こういうのは全ページで同じであることが(基本的には)保証されてたほうがいいんで。

追記

共通にしといて、if文とかで分岐させないとだめになったらそのタイミングでバラすというのも手だとは思います。ただ、複数人で開発とかしてると設計の変更って分岐追加するよりMP消費するから、どうしても最初の設計にひっぱられがちになるというのは感じてて、今回の例のように関心がそもそも違うみたいな場合は別にしちゃうほうが筋が良さそうだなーと思います。

スロークッカーとかいうぐう有能調理器具wwwwwwww

はじめに

プログラマツイッターユーザの間では、誕生日とか退職とか就職とか引っ越しとか結婚とかそういう節目のタイミングでアマゾンの欲しいものリストを公開しプレゼントを請うという文化が存在します。不肖私もこのたび 2月13日に無事31歳の誕生日を迎えることとなりまして、浅ましくも欲しいものリストを公開したところ、ハリボのグミが1.4kgのほか、ウイスキーが約1.5リットル、KORGのクリップチューナー、アイカツのCD、さらには大物としてスロークッカーという調理器具を友人各位からいただきました。本当に友人に恵まれていて感謝以外の感情がない。各位におかれましては必ず誕生日にwishlistを私宛に送るように。恩に報いる所存です。

f:id:nkgt_chkonk:20150214125536j:plain

amazonの箱のチョイスがおかしい様子です

f:id:nkgt_chkonk:20150214131542j:plain

ゴールデンベアとハッピーコーラです

f:id:nkgt_chkonk:20150214125956j:plain

日本が誇るウイスキー、白州です。

f:id:nkgt_chkonk:20150214181156j:plain

Signalize!とカレンダーガールが収録されています。カレンダーガールは名曲中の名曲です。

f:id:nkgt_chkonk:20150215172410j:plain

癖のあるウイスキー好きにとっての定番、ラフロイグです。

f:id:nkgt_chkonk:20150215172348j:plain

スロークッカーだ!!!!!!!!!!!!!!!!!!!!

ところで、このスロークッカーという調理器具(写真ではダンボールに入ってるけど)はどういうものかというと、簡単にいうと「電気の力で弱火状態をずーっと保持してくれる君」なのです。ものによってはタイマー付きで、時間が来ると勝手に電源切ってくれます。

これ、いろいろとうれしいんですよ。ガスの力で弱火を保持しようと思うと、結局それって火を扱ってるのでそうそう簡単にキッチンを離れることができません。たまに火の様子見に行ったりしないとだめだし。あと、コンロを一口占領しちゃうのも困りものですよね。とくに「弱火でじっくり」系の料理ってすごく長い時間コンロを占領しちゃうので、なにかと困ります。そこで考え付くのが低温調理の雄としてよく挙げられる炊飯器ですが、炊飯器も長時間占領されちゃうとお米が炊けないという問題があります。そこでスロークッカーの出番になるわけです。スロークッカーによってわたしたちは、コンロのことも炊飯器のことも火の元のことも気にせず煮込み料理を遂行する自由を手にいれるのです。

誕生日にスロークッカーをいただいたのが本当に嬉しかったので、急遽スペアリブを買ってきて、こいつを煮込んでみることにしました。以下その工程であります。

スペアリブをホッロホロにしてやろう

f:id:nkgt_chkonk:20150216004144j:plain

はい。スペアリブを買ってきました。ちょっとお安くなっていてお得ですね。新潟市に特有のスーパーマーケットである清水フードのマークが見えて住所が特定されかねない気がしますが気にせずいきます。

f:id:nkgt_chkonk:20150216004325j:plain

表面に焼き色をつけるという工程を行っているところです。

f:id:nkgt_chkonk:20150216004928j:plain

肉を煮込むときにはまず普通に茹でてアクを取り除きましょう。

f:id:nkgt_chkonk:20150216010015j:plain

こちらはアクを取り除いたあと茹で汁を捨て、煮汁とともにスロークッカーに投入した様子です。煮汁は酒、砂糖、みりん、醤油、しょうがを適当にお湯にぶっこんだものです。写真を見るとわかるかと思いますが、パーソナルコンピュータで仕事の進捗を出していると、隣でスロークッカーが自動的に調理の進捗を出してくれるというCI(継続的インテグレーション)体制を敷くことが可能となっております。(PCとの距離が近すぎて熱が危なかったのでこのあとちょっと場所を移動しました)

f:id:nkgt_chkonk:20150216030548j:plain

スロークッカーが自動的に肉をビルドしている様子です。

f:id:nkgt_chkonk:20150216053502j:plain

ビルドが無事成功した様子です。

f:id:nkgt_chkonk:20150216053526j:plain

箸を入れたら、全く力を入れていないにもかかわらず骨から肉が分離されました。こういうのを骨と肉の疎結合と言います。プログラムの設計において非常に重要な概念ですね。

f:id:nkgt_chkonk:20150216053533j:plain

こちらが成果物です。控えめに言って最高にうまい。

前回の「タイ風豚の角煮」をこれで作るのも良さそう。

まとめ

  • 誕生日にアマゾンの欲しいものリスト公開したらみんなの愛が最高にうれしかった
  • なんとそのなかにスロークッカーとかいう有能すぎる調理器具が!!
  • 試しにスペアリブを煮てみました。
  • スロークッカーはCIツールである
  • 骨と肉の疎結合を実現することも可能である。

誕生日プレゼントをくださったみなさん、ほんとうにありがとうございました。

タイ風角煮考

ここ最近角煮が話題かどうか知りませんが角煮です。

角煮ですが、うまいし簡単に作れるのですが時間がかかります。とはいえ、タイ風角煮なら雑に作ってもうまいという知見があるのでシェアします。

まず、角煮が硬くなるのは調味料で煮る、そのタイミングです。このタイ風角煮はその工程をまるっと無視して、タイ風のたれをかけて食べるものなので、雑に作ってもほろほろの角煮が出来上がります。ただし圧力鍋は必須です。圧力鍋は角煮に限らず煮込み料理がはかどりまくるのでないひとはこの機会に買いましょう。

材料は以下のとおりです。

下ごしらえ

豚バラブロックは適当なサイズに切っておきます。しょうがは皮をむいて(皮は捨てない)、すりおろしておきます。みじん切りでもいいです。

豚バラを雑に圧力鍋で煮る

豚バラブロックを適当なサイズに切って、しょうがの皮の部分とネギと一緒に圧力鍋で雑に煮ます。私はいつも時間は適当にやってますが適当な時間煮込んだだけでも十分うまいです。

別の鍋でキャベツを茹でる

豚バラは結構油がしつこいので、キャベツと一緒にたべるといいでしょう。キャベツは千切りでもいいんですけど、この豚の角煮の場合茹でた方が合う気がします。

タイ風たれを作る

小鍋に、トムヤムクンのもとを適当な量(わたしはいつも計ってないです)と、豚を煮た煮汁をおたま一杯分くらいと、すりおろしたしょうが、ナンプラー、レモン汁を入れて煮詰めます。お好みでパクチーも入れるとよいでしょう。ここの味は好みの問題なんで、それぞれ好きな量入れれば良いです。わたしはいつも味を見ながら雑に投入してます。

トムヤムクンのもとですが、わたしは高円寺北口にある「東京屋」とかいう怪しげな店で買った瓶づめのやつをいつも使っています。

この店です https://www.google.co.jp/maps/@35.705495,139.649401,3a,75y,328.63h,99.9t/data=!3m4!1e1!3m2!1sHr6DitUq-jbcCeGRp9FAJw!2e0

このタレはけっこう万能で、どんなものでもタイ風の味付けにできる優れものなので、トムヤムクンを作らないとしてもトムヤムクンのもとを常備しておくと良いでしょう。いつでも手軽にタイっぽい味が楽しめるのでおすすめです。

盛り付ける

茹でたキャベツを持ったお皿に、味のついていない豚の角煮を盛り、その上からたれをこれでもかというくらいにかけます。その上にお好みでパクチーを散らして完成。

雑に作ってもいつもおいしくできるし、妻や友人たちの評判も良いし、ごちそう感のあるメニューですので、ぜひ大量に作って家族や友人たちと大量に食べてください。

@sasaplus1 さんの神対応によって process-bookがwebで読みやすくなりました

process-book ってなに

この文書はなんですか?

この文書は*nix系のシステムにおけるプロセスやシグナルなどについて説明することを目的に書かれました。「プロセスとかよくわかってないからちゃんと知りたいな」みたいなひとたちが想定読者です。

書いているあいだは gist で管理されていたのですが、ボリュームが大きくなったので github で管理するように変えました。

というやつです。結構頑張って書いたんですけど、その結果結構いろんな人に褒めていただけて、本当にありがたいなという感じです。ありがとうございます、ありがとうございます。

実は大きなトピックとして「環境変数」についてまったく触れられてなくて、そこは「あちゃー」って感じなんですけど、いつか気が向いたら追記するかもしれません。気が向かなかったら追記しないので、気が向くといいなと思っています。

どこで読めるの

process-book

どういう経緯なの

ちょっと前に「gh-pagesに対応したブランチ作ったから見て」って @sasaplus1 さんから言われてて、「おっありがたい、あとでみよーっと」って思ってたらそのまま忘却の彼方にアレしてしまっていたのですが、今回 Github の issue にコメントをいただいたことで思い出して、それをそのまま、ほんとにそのまま取り込ませていただいたという形です。

ありがとうございました & 放置しててすみませんでした。めっちゃ神対応な感じだったんで今度 :beer: おごります……。

swift の protocol の解決が Playground 上でうまくいかないっぽい話

えー。尊敬するiOSアプリケーションプログラマのひとりであるdictavさんがこういうものを上げておりました。

Logger for Swift

これを見て最初に思ったのが、「static var とかセオリーで考えたら「ねーよ」っていう感じだけど、この場合に限ってはうまく作用してておもしろいな」でした。

その次に思ったのが、「あっでも description に関しては var である必要なくない?」でした。というのも、この desciption は固定でいいはずだから。

しかし、この var description は、そもそも Printable プロトコル(ジャバで言う所のinterfaceみたいなもんや)が要求するするものであるので、そもそも「description は let でよくない?」というのは的外れな考えですね。

というわけで、Printable プロトコルについて調べてみましょう。

Printable プロトコルとは

Swift Standard Library Reference: Printable

ここに全部書いてある。要するにそのクラスのインスタンスを文字列化するときにどういう形で文字列化するかっていうのを var description というところに定義しておいてね、っていうプロトコルです。

試してみる

で、これをみて私はまず「enum が Printable プロトコル実装できるのおもしろいな〜」って思って、Xcode の Playground でこういうふうに書いてみたんですね。

http://i.gyazo.com/70dda2bb1299d383cae6dcf8ac961616.png

あっあれーーーーー!?println(Nyan.Nyaa.description)はちゃんと "にゃー" を返すのにprintln(Nyan.Nyaa)が"(Enum Value)"を返す!?!?!?!?!?

というのを見て「なにこれどういうこと」と困惑していたら、Twitterから「これアンドキュメンテドだけど、Xcodeでちゃんとプロジェクト作ってビルドするとprintln(Nyan.Nyaa)も"にゃー"だよ」という情報を得ました。そこで私は「あれっこれ(つまり enum の この挙動)って要するに「未定義」な振る舞いなんじゃないの」って思ってしまったんですね。疑問に思ったら一次情報に当たるのがプログラマのたしなみです。仕様上の定義を探す旅に出ましょう。

まずはレキシカルな仕様を調べる

まずは言語のLexicalな仕様を当たりましょう。これは要するに「そのプログラムを文字列的(形式言語的)に解釈したときにただしいプログラムとして受理できるかどうか」を調べることにあたります。

The Swift Programming Language: Lexical Structure

Lexicalな仕様がきちんと公開されていました。

この中で関係ありそうなのは The Swift Programming Language: Declarationsenum-declaration の部分で、抜粋すると

http://i.gyazo.com/92923d52b9aeaadfe2b0137341031b64.png

とあります。enum-declaration の部分をみると、enumの定義が受理する文字列のルールはふたつあるようです。

今の関心は

enum Nyan : Printable {
    case Nyaa, Mew
    var description: String {
        switch self {
        case .Nyaa: return "にゃー"
        case .Mew: return "みゅー"
        }
    }
}

なので、多分 attributes と access_level-modifier は(optionalだし)関係ないだろうなとあたりをつけ、union-style-enum­ が受理する文字列や ­raw-value-style-enum­ が受理する文字列をさらに見ていきます。swift をちょっと知ってると、上に見た文法はraw-value-styleではないとわかるので、union-value-style-enumにあたりをつけてみていきましょう。   まず、union-value-style-enum は 以下のルールを受理します。

enum(固定文字列) ­enum-name­ generic-parameter-clause(­opt) ­type-inheritance-clause(­opt) ­{ ­union-style-enum-members­(opt)­}

ここから、Nyanの定義のうち "Nyan" が "enum-name" であり ":Printable" が ­type-inheritance-clause であることが推測できます。 深追いはしませんが enum-name は Nyan を受理するし type-inheritance-clause は " : Printable" を受理することが同様に深追いしていくとわかります。

さて、問題は ­union-style-enum-members­(opt)­ です。こいつが

    case Nyaa, Mew
    var description: String {
        switch self {
        case .Nyaa: return "にゃー"
        case .Mew: return "みゅー"
        }
    }

を受理するかどうがが今一番の関心ですが、union-style-enum-membersunion-style-enum-member union-style-enum-members(opt)となっており、union-style-enum-member複数集まったものだと見て取れます。で、union-style-enum-member は declaration | union-style-enum-case-clause­ とあり、今回の例で言えば case Nyaa, Mewunion-style-enum-case-clause­にあたり、var destription 以下がdeclaration­ に当たることが推測できます。で、実際にこいつらをさらに追ってみると、上記のようなNyan enumの定義がレキシカルには受理されるべきものであるということが確認できます(実際に追ってみてください)。

さて、これでこれが「レキシカルには受理されるべきものだ」ということが確認できました。

次は意味を調べる

では、次は enum における computed property (var varname: Type { codeblock } みたいなやつはcomputed property と呼ばれる)が言語仕様上どういう意味を持つのかってことを見ていく段階ですね。探すと、出て来ました。

The Swift Programming Language: Enumerations

Enumerations in Swift are first-class types in their own right. They adopt many features traditionally supported only by classes, such as computed properties to provide additional information about the enumeration’s current value, and instance methods to provide functionality related to the values the enumeration represents.

なるほど、computed property は普通のクラスみたいに使えるよ、と書いてありますね。ということは、この挙動は別に未定義なわけではなくて、Xcodeでプロジェクト作ってビルドしたときの挙動が「swiftの仕様上ただしい挙動である」と言えそうです。

じゃあなんでPlayground上では仕様と異なる動きをするの?

これ、どうやら Playground が依存している LLDB 上の制限っぽいです。たとえば、以下のような(enumと関係ない)例を見てみてください。

http://i.gyazo.com/05d24ffaaeb3428bb37fc25f7961c230.png

普通にPrintableを実装した Nyan クラスのインスタンスが println に対応していません。そして lldb のなんかの値が吐かれています。つまり、多分これって、静的に解決すべき 「Nyan is a Printable」な関係がLLDBの制限によって静的に解決できなくて、そのせいでうまく動いてない、ということなんでしょうね(仮説です)。

この仮説の正否と、なぜ LLDB 上で Printable が解決できないかについてはおそらく dictav さんがブログで解明してくれるでしょう!期待して全裸待機!!!!