てくのろじーたのしー

Haskellぺろぺろ

PIXIV SPRING BOOT CAMP2018に参加しました!

pixiv SPRING BOOT CAMP 2018とは

参加すると圧倒的猛者になれるようです。

f:id:techno_tanoC:20180307204459p:plain

pixiv SPRING BOOT CAMP 2018はピクシブ株式会社(以下ピクシブ)で行われた春のインターンシップで、今回は2/26から3/2までの5日間開催されました。

遠方からの参加者に対しては交通費の負担とホテルの手配をしていただける時点でかなり太っ腹だと思うのですが、その上もれなく全員に日給1万円まで支給される(つまり5日間で5万円!!)(圧倒的感謝!!)という、待遇の時点で「インターンシップとはなんなのか」と常識を覆されるインターンシップです。

このインターンシップには3つの部門から成る8つのコースが用意されています。

  • WEB開発
    • pixivコース
    • BOOTHコース
    • Pawooコース
  • アプリ開発
    • pixivコース
    • pixivコミックコース
    • pixiv PAYコース
  • サービス基盤

僕はRuby on Railsの経験があったため、この中のBOOTHコースを志望しました。

BOOTHを知らない方のために少し説明をします。

イラストがたくさん投稿されているサイトとしてpixivは有名だと思うのですが、ピクシブはpixiv本体以外にも多くの事業を行っています。 その中の一つにRuby on Railsで構築されているBOOTHというサービスがあります。BOOTHはpixivなどで活躍しているクリエーターの方が作った作品が多数出品されており、ユーザは好きな作品を購入することができます。イラストや漫画に限らず音楽やアクセサリーなども出品されており、作品の幅はとても広いです。

そして実はBOOTHには技術書も出品されており、僕も以前Elixirの本を買ったことがあります。エンジニアの方、エンジニア志望の方は探してみると自分の興味のある分野の本が見つかるかもしれません。

hayabusa333.booth.pm hayabusa333.booth.pm hayabusa333.booth.pm


選考

選考フローには提出書類でエントリーする通常選考とGitHubのアカウントでエントリーするGitHub選考があります。どちらの選考フローでも書類選考、GitHub選考の後に面接があります。 僕はGitHubに置いてあるコードにあまり自信がなかったので、通常選考でエントリーしました。

僕は薬学部なので選考の時点で何かしらマイナスになるかもしれないと思っていたのですが、選考を通過することができたので情報学部、工学部以外の方も開発やプロダクトに対する思いをぶつければちゃんと評価してもらえると思います。

そんなわけで僕は圧倒的猛者になるべく、ピクシブへと赴きました。

俺、ピクシブで圧倒的猛者になるんだ・・・(死亡フラグ


出社チャレンジ失敗

初日に遅刻しました(死亡フラグ回収

原因は開かずの踏切で20分足止めを食らったことです。 他のインターン参加者の方々、メンターの方々にはご迷惑をおかけしました。すみません・・・

僕と同じ轍を踏む人が現れないように詳細と対策を書きます。

問題の地点はここです。ここの踏切は運が悪いとずっと開きません。

そしてこちらのルートと通れば開かずの踏切を回避できます。

そんなわけで僕のインターンシップは遅刻で幕を開けることとなりました。出社チャレンジに失敗する奴が圧倒的猛者になれるのでしょうか?


インターンシップ開始!

参加者とメンターの方々の自己紹介が終わった後、一緒に食事を摂り、いよいよ各コースでインターンシップが始まります。

初日は主に開発環境の構築をしました。BOOTHではいくつかのミドルウェアを利用しており、その辺りのセットアップマニュアルがMac向けとなっていたため、Linuxを使っていた僕は若干苦労しました。夕方ごろにはDockerでミドルウェアを動かすことで手元でBOOTHが動きました。

僕のノートは中古で買ったThinkpadなのですが、メモリが4GBしかなく非常につらかったです。Chromeを使うとメモリをモリモリ食べ始めるのでFireFoxを使っていました。

普段はBOOTHほど大きいものを扱うことがないのでこのスペックで困ることはなかったのですが、メモリの必要性を強く感じました。メモリは人権。


開発開始

最初はView周りのの軽いissueを2つ解決しました。軽いというのは最終的なコードの変更が少ないという意味で、内容は色々と議論がなされました。どのように変更すればユーザは嬉しいのか、どのように変更すれば可読性や保守性が高まるのか、しっかりと議論とレビューがされるのでたくさんコメントをもらいながら開発をしました。

火曜日には1つ目のissueの修正がマージされ、デプロイされたのでテンションが上がりました。BOOTHはデプロイツールを使っており、GUIでポチポチと操作すればデプロイされ、本番環境に反映されていました。実際にサービスに反映された時はとても嬉しかったです。


野菜ジュースがおいしい

f:id:techno_tanoC:20180307214335j:plain

ピクシブにはフリードリンクがあり、冷蔵庫に入っている飲み物が飲み放題です。 常日頃から野菜不足を実感している僕はずっと野菜ジュースばかり飲んでいました。ぽっぴっぽー。

野菜ジュースがたくさん飲みたい人はピクシブに行きましょう。

(ちなみにピクシブに置いてあるのは野菜生○100ではないです)

でも野菜ジュースだけ飲めば栄養面で万事オッケーとなるかは知らないので食事はバランス良く摂ることが大事だと思います。


水曜日はイベントがいっぱい

水曜日にはラジオ体操、全体会議、全体ランチがあります。全社員が集まるのでちょっとしたイベントですね。

f:id:techno_tanoC:20180308181339j:plain

全体ランチのご飯


APIを生やす

View周りのissueを倒し終わったころ、大きめのタスクを任されました。モバイルアプリ向けのフォロー一覧APIを作るというタスクです。

当時、アプリではフォロー一覧を表示することができなかったため、フォローを解除するにはそれぞれのショップのページを開いて一つ一つフォローを外していく必要がありました。今回はフォローしているショップを一覧で返すことで、フォロー一覧を見たり、解除することができるようにするための機能追加です。

実装の手順をざっくりと分解すると

  • ルートを生やす
  • Controller追加
  • JSONを作るViewを作る
  • rspecのテストを追加
  • swaggerの作成

といったところです。railsrspecを使って開発する経験は多少あったのでこの辺の大まかな作り方は知っていました。

が、レビューが実際に通ったのは木曜日の昼過ぎ。意外と時間がかかりました。というのも開発に着手してから、色々と想定外、想定不足が発生したからです。

  • 生やしたルートが別のルートと干渉して到達不能になった
  • 変数名はもっと分かりやすい変数名があるのではないか
  • 返すデータの順番はどうするのか、ソートはどうやって行うべきか
  • テストをリファクタリングしたらなぜか動かなくなる
  • レスポンスのJSONに含まれるデータはこれで良いのか

と、ちゃんと考えていないがゆえに発生した問題が多々ありました。 予想では簡単に思えても実際にやってみると色々な問題が出てくるものですね。リアルワールドの問題は難しいです。

メンターの方に相談したり教えてもらったりしながら問題を解決し、その後無事マージ・デプロイされました。

事前にBOOTHのアプリを開発している方がデバッグビルドでそのAPIを使う部分を作ってくださっていたので、デプロイ後実機でその機能を見ることができました。なんか、自分が作ったものがちゃんと機能しているのを見るとテンション上がりますね。そのうちその機能が入ったもののアップデートが来ると思うので、自分のスマホで見てニヤニヤすることになりそうです。


leadsヘルパーの提案

僕が前から使っているRSpecのヘルパーにleadsというものがあります。

インターンシップ中にこのヘルパーの導入を提案、実装、一部導入をしました。インターンシップ中にマージまではされていないので、今後どうなるかは不明です。

これは「subjectにはテスト対象を書く場所として統一したい」という思いから生まれたもので、例えばコントローラーのテストが以下のようだったとします。

describe HogeController do
  describe 'index' do
    before { get :index }
    it { expect(response).to be_success }
  end

  describe 'create' do
    it do
      expect {
        post :create
      }.to change(Hoge, :count).by(1)
    end
  end
end

パラメータなどは省略したので雰囲気までに。

leadsを使うと以下のようにリファクタリングできます。

describe HogeController do
  describe 'index' do
    subject { get :index }
    it { leads{response}.to be success }
  end

  describe 'create' do
    subject { post :create }
    it { leads.to change(Hoge, :count).by(1)
  end
end

コントローラーのように本質的に副作用がメインとなる処理のテストでは非常に見通しが良くなります。is_expectedと併用することで、より「subjectはテスト対象を書く場所」と統一することができるようになると思います。


KPT

1日の最後にはKPTを書きます。KeepProblemTryの略らしいです。

簡単に言うと良かったこと問題今後することみたいなものです。

f:id:techno_tanoC:20180307221804p:plain f:id:techno_tanoC:20180307221811p:plain f:id:techno_tanoC:20180307221821p:plain f:id:techno_tanoC:20180307221825p:plain

「コロッケで学ぶgit」というのはのんさこ君が牛肉コロッケを食べて「じゃがいもが美味しい」と言った際に僕が「じゃがいもと牛肉がコンフリした結果牛肉が消えた」と言ったのが元ネタです。他の人がKPTで「コロッケで学ぶgit」と書いたので僕も書きました。

Rustとかアラビア人とかはRustやC++のすごい人と色々話した時のものです。 アラビア人ってどうやってコード書いているんでしょうね?普段読む文章が右から左だと、左から右に書くのがすごく大変そう。


まとめ

・野菜ジュースをたくさん飲んで野菜不足が多少解決された気がします。結局圧倒的猛者とは何なのかは分かりませんでしたが、ちょっと健康にはなれたかと思います。

※追記 総メンターのchocomelonさん曰く、「大きな規模のサービス/コードベースに一週間でデプロイまで達するのはかなり難しい。それをメンターがサポートしながら達成することで圧倒的な猛者になったことを実感して欲しい!というお気持ち」とのことです。

・メンターの人は優しいので分からないことがあったら長いこと悩まず、早めに質問をした方が良いです。密なコミュニケーションはやっぱり大事で、コンセンサスが取れていないと勘違いが発生したりします。

ピクシブに一週間いて思ったことは、とにかく社風がカジュアルで自由なことです。働いている方々もフレンドリーで、気軽に話すことができました。

最後に一言

ピクシブインターンはいいぞ」


写真

f:id:techno_tanoC:20180308181609j:plain f:id:techno_tanoC:20180308181612j:plain f:id:techno_tanoC:20180308181603j:plain f:id:techno_tanoC:20180308181710j:plain f:id:techno_tanoC:20180308181554j:plain

自分のプログラミング遍歴

なぜこれを書くか

年末には大掃除しますよね?そういうことです。

プログラミング歴も5年半を超え、色々なことがあったのでまとめておきます。できるだけ時系列順に書いていますが同じ時期に起こったことや長期間に渡る話もあるので正確性には欠けると思います。

自分用PC

「なぜプログラミングを始めたのですか?」

最近、IT企業の方と真面目な話をすることが増えたせいかこう尋ねられることが増えました。

プログラミングを始めた時期は今から5年半ほど前になります。大学に入る前に自分用のノートPCを買ってもらいました。確か「大学に入ればWordとかで課題を提出することもあるだろうから」という名目で与えられたものだったと思います。数年前に妹に譲渡したので詳しい型番やスペックは分からないのですが、Windows7の白いノートPCでした。普通の家電量販店で買ったのでどこかのメーカのものだったはずです。値段も判然としないのですが6, 7万円ほどだったかと。当時、パソコンを使う機会と言えば、ゲームの攻略wikiを見る時ぐらいのものだったため、買う時も特に何も考えずに選んだ気がします。

脱線しますが、twitterは大学に入る1年ほど前からPSPのブラウザ機能を使って、軽量のtwitterクライアントでやっていました。techno_tanoCというアカウントではありませんでしたが。

ともかく、大学に入る1ヶ月ほど前に自分用のノートPCを入手しました。前述したように当初はゲームの攻略wikiを見るためぐらいの認識だったのですが、少し経ってからニコニコ生放送を見るようになりました。竹島さんの放送が大好きで、ずっと見てました。\キャーオーバーレイサーン/

冒頭の質問を投げかけられると基本的に「自分用のPCを手に入れた時になんとなく」と言っているわけですが、実は買ってしばらくはプログラミングを始めるとは夢にも思っていませんでした。

プログラミングを始めた理由なのですが、当初はただの暇潰しでした。あの暇潰しが5年以上続くわけですから人生何があるか分からないものですね。プログラミングをする理由はいくつか思いつくのですが、プログラミングを始めた理由なんて無いに等しいです。強いて言うなら家系かもしれません。これはプログラミングを始めて数年経ってから知ったのですが、父方の叔父は元SEで、父親は昔趣味でBASICやFORTRANを書いていたらしいです。血というのはげに恐ろしきかな、僕も血には抗えなかったのでしょうか?

C++は最強らしい

そんなこんなで大学のために田舎から山口から都会の兵庫県に引っ越しました。

部屋でいつものようにtwitterをしていると、プログラミング言語に関するツイートが流れてきました。曰く、「C++は最強。これがあれば何でもできる。速度も早くてwindowsのアプリケーションも作れる」。特に深く考えることもなくググってみるとC++はどうもすごいものらしい。

最初は「暇だしやってみるか」ぐらいのノリでした。本を買うのも面倒ですし、かわいい猫の写真に釣られて猫でもわかるプログラミングというサイトでC++に入門しました。

C++を始めたと言ったな。あれは嘘だ

1週間で挫折しました。

いや、頑張ったんですよ?何も知らない初心者がwindowsコンパイラ入れて、テキストエディタにぽちぽちソースコードを打ち、コンパイラ様に怒られながらソースコードとにらめっこ。

でもコンストラクタで挫折しました。「コンストラクタってなんだ」。

猫様がおっしゃるには

[作り方手順]
1.コンストラクタは、クラスの名前と同じ名前である。
2.コンストラクタは、引数を取ることができる。
3.コンストラクタは、戻り値がない(注:void型ではない)
4.デストラクタは、クラスの名前の前にチルダを付ける。
5.デストラクタは、引数がない。戻り値もない
6.コンストラクタもデストラクタも省略されると暗黙のうちに
  引数や、中身のない関数が定義されている。
7.コンストラクタもデストラクタもpublicな関数である。

らしいです。完全に「おまえは何を言っているんだ」状態。

f:id:techno_tanoC:20171224181910j:plain

今となってはコンストラクタは常識どころか呼吸レベルですが、当時はオブジェクト指向のオの字も知らないド素人です。

当時は

  • 「そういえば関数って数学で習ったぞ」
  • 「つまりコンストラクタは二次元座標のx軸とy軸みたいなもんなんだろうな!」
  • 「じゃあデストラクタってなんだ?」
  • 「なんでクラスと同じ名前なんだ?」

とか明後日の方向に思考が飛んで、どうにもならない状態でした。

コンストラクタが分からないならC言語をやればいいじゃない

今思えばC言語もできないのにC++ができるわけないです。当時の僕もそれに気づいたのか、猫様の下でC言語を学び始めました。

C言語の勉強はそこそこ上手くいき、どこかで見つけた素数列挙プログラムを書いてニヤニヤしていました。アルゴリズムは確か、「nを2以上n未満の数字で割ってみて、割り切れなければ素数。それをnをカウントアップしながら繰り返す」だったと思います。ズラズラ出てくる素数、だんだん見つかるのが遅くなる素数素数の列を見ながら奇妙な満足感を得ていました。学校の授業中にノートにそのプログラムを書いてアルゴリズムをトレースしてはちゃんと動くことを確認していた記憶があります。

最終的にはビットマップで画像処理のを参考に、「BMPファイルをアスキーアートもどきに変換するプログラム」を作りました。大層なものではなく、画素ごとに明度をもとに数種類の文字から選択して出力しただけのものです。遠目で見ればちゃんともとの画像が分かる程度のものでしたが、まどマギの画像をAA化して友達に見せたりしていました。意外とBMPフォーマットって簡単なんですよね。

ソースコードこちら

C言語時代に書いたコードを探してみたのですが、これ以外は見つかりませんでした。残念。多分C++, C言語C#Javaソースコードはほぼ全て喪失しています。

C#は楽だった

実際に役に立つプログラムを作るにはGUIの方が楽ということでC#を始めました。VisualStudioはすごいもので、GUIGUIを作れるんですよね。分からない方のために説明すると、以下のようにツールボックスからデザイン画面にD&Dして、プロパティを設定するだけでそこそこいい感じのGUIがデザインできてしまいます。

f:id:techno_tanoC:20171224190631j:plain

あとは各コンポーネントに対応するクラスのイベントハンドラに処理を書けば動くわけです。

最初に作ったちゃんと使えるようなものは確かこれまたどこかのサイトを参考にした電卓だったと思います。四則演算、べき乗、消費税の計算などの機能があったと思います。

C#ではいくつかのソフトを作りました。覚えている範囲では、

  • 1つのウィンドウを分割して同時に2つのサイトを見れるブラウザ
  • RSSを表示するサーバプログラム(当時はHTTPという便利なものを知らなかったのでTCPで無理やり文字列を送っていました)
  • ニコニコ動画APIを叩き、キリ番一歩手前の動画を探し、キリ番を踏むためのコンソールアプリ
  • Vistaで入ったDWM(Desktop Window Manager)を用いたウィンドウのサムネイルを一覧化し、クリックするとそのウィンドウがアクティブになるタスクスイッチャー
  • 好きな画像をもとに15パズルを生成して遊べるゲーム

などを作りました。例によってソースコードはもうありません。

特に後半の3つは思い入れがあります。

ニコニコ動画APIを叩くものは、実装そのものよりも後述する関数型プログラミングの話になります。

 

DWMという言葉を知らない人でも、Vistaでタスクバーにあるアプリの部分にカーソルを乗せた時に表示されるリアルタイムのサムネイルを見たことがある人は多いのではないでしょうか?

f:id:techno_tanoC:20171224193407p:plain

タスクスイッチャーの方はこれを一覧化したものでした。 APIの叩き方はProgramming the Windows Vista DWM in C# - B# .NET Blogを見ながら作りました。

いつ消えるかも分からない古いサイトなのでウェブ魚拓https://megalodon.jp/2017-1224-1925-09/bartdesmet.net/blogs/bart/archive/2006/10/05/4495.aspxmegalodon.jp

同時に全てのウィンドウを見ることができたので、他のウィンドウの状況を見ながら作業する時には便利でした。このサムネイル、ウィンドウと同じ解像度を持っているので、大きく表示すればちゃんと文字まで見えるんですよね。

 

15パズルというのは以下のようなものです。あくまでイメージで、実際に作ったものとは違います。

f:id:techno_tanoC:20171224193645p:plain

jpgなどの画像をD&Dすると画像を16分割して、シャッフルして、プレイヤーはバラバラになった絵をピースをスライドさせて完成させるというものでした。

シャッフルは適当なピースをランダムに動かして行うものだったと思います。確か下手に入れ替えると解けないパズルになることがあるので。

このゲームは徹夜をして作った思い出があります。当時は「テスト」なんて便利なものをしらないので、デバッグがなかなか終わらず、ソースをいじっては動かしいじっては動かしを繰り返していました。デバッグの時間の内、けっこうな時間は実際にパズルを解いていたかもしれません(笑)。

Androidアプリが作りたい

C#で色々作ってる間に、並行してAndroidアプリの作り方も学びました。特に始めた理由はないのですが、使っていたのがAndroidだったので作ってみたくなったのだと思います。(ちなみに悪名高きARROWSのISW11Fでした。F士通が嫌いになりました)

Androidアプリでも色々作ろうとしていました。Eclipse上でAndroidアプリのプロジェクトがうまく作れなくて1ヶ月コードを書くところまで辿りつけなかったのは良い思い出(良くない)。

結局実用に至るレベルのものは作れなかったのですが、

  • Dropboxに置いてある音楽ファイルをストリーミングで再生する
  • USB接続したwindows上にある動画ファイルをストリーミングで再生する
  • URLを指定するとファイルをダウンロードするアプリ(未完成)
  • OpenGLで立方体を回すだけ
  • 音楽プレイヤー(未完成)

などを作りました。

最初の2つは実際に再生ができるだけの部分しか作っていません。

確かUSB接続したwindows上にある動画ファイルを再生するアプリは、アプリの裏側でプロキシとなるwebサーバを立てて、そこからのストリーミングで再生するような実装だったと思います。Androidはwebサーバからのデータをストリーミング再生できるので無理やりそういう実装にしました。

多分この辺りまでがプログラミングを始めて1年か1年半ぐらいまでだったと思います。

基本情報技術者応用情報技術者試験

プログラミングを始めて1年ほどで基本情報技術者を取得しました。その半年後には応用情報技術者を取得しました。

僕の家はちょっとスキル主義なところがあって、小学生の頃にはハンダ付けやノコギリ、金槌の使い方からネジの締め方まで、父親から教わっていました。その延長線上に資格取得はあります。

小学6年生の時に第4級アマチュア無線技士、中学2年生の時に丙種危険物取扱者と乙種第4類危険物取扱者、高校2年生の時には二級小型船舶操縦士を取得しました。

上記の資格は特段難しいものではなく、父親曰く「資格取得の体験をさせるのが目的」だったようです。「こういう資格取ってみるか?」と聞かれ、それに乗っかる形で勉強しました。両親とも資格を要求される仕事に就いていたため、僕自身も資格に対する漠然とした憧れは幼少の頃からあり、資格取得には意欲的だったと思います。ただし資格自体が役に立ったことはありません。

さて、上記の資格は「取ると決めてから勉強を始めた」という形なのですが、情報技術者の資格は違います。

大学に入ってからプログラミングを始め、ある時ふと思いました。「一介の薬学生が『プログラミングを勉強しました』と言ってどこまで信用されるのか。そもそもちゃんと勉強したと言えるのか。資格を取って客観的に証明してやろう」。早速ネットで検索してみると基本情報技術者というのがあるようです。その後本屋でその参考書を立ち読みしてみました。感想としては「なんだ意外と知ってることばっかりだ」。C言語アルゴリズムの基本を、C#でネットワークの基本を、AndroidJavaSQLiteを知っていたのが幸いして、あとは暗記すべき点を暗記すれば勉強は終わりました。同様に半年後に応用情報技術者を勉強して合格しました。

ちなみに調子に乗ってその後にデータベーススペシャリストネットワークスペシャリストを受けたのですが不合格でした。その頃から学校の勉強に追われるようになったため、再挑戦は叶わず。いつか再挑戦したいものです。

関数型との出会い

Rubyを始めるのと関数型プログラミングを始めるのは時期的に近いのですが、先に関数型プログラミングについて書きます。

前述したように関数型プログラミングとの出会いはニコニコ動画APIを叩くライブラリです。githubニコニコ動画APIを叩くライブラリを見つけてそのソースを読んでいる時でした。C#にはLINQという機能があり、そのメソッド構文ではラムダ式を使ってリスト処理ができます。ラムダ式を始めて見た瞬間に「プログラミングにはこんなに物事を簡潔に書くことができる機能があるのか!!!」と衝撃を受けました。後から思えばこれが関数型プログラミングとの出会いでした。

そういうわけでラムダ式を知り、関数型プログラミングの存在を知り、Haskellを知りました。『すごいH本』を読んでHaskellを勉強しました。

Haskellは素晴らしい言語です。ここでは多くを語ることはしませんが、代数的データ型、パターンマッチ、オフサイドルール、モナドなどなど今までの言語とは全く違う世界が広がっており、その簡潔で安全な性質に魅了され、その後のプログラミング観に大きな影響を与えました。

勉強会初参加 Python?いやRubyだ!

AndroidJavaを触っているうちに、近くでJavaの勉強会が開かれているようだったので参加しました。初勉強会参加です。

そこからいくつかの勉強会に参加するようになりました。

当時は「そろそろスクリプト言語もやりたいなぁ」「とりあえずPythonやるかー」などと下手の横好きなことを考えて、『パーフェクトPython』を買いました。しかし直後にRubyの勉強会に参加し、Rubyをメインに触るようになったのでPythonはこの本を読んだだけで終わってしまいました。そういえばRubyの本は一冊も買っていません。借りた『メタプログラミングRuby』を読んだぐらいでしょうか。

というわけでRubyの勉強会に参加したのですが、それがあの有名な(?)、神戸.rb(当時は東灘.rb)です。

Rubyの言語仕様を知らないどころか、RubyすらインストールされていないノートPCを抱えて参加するという、今思えば大変申し訳ない状態での参加でした。しかもあろうことかペアプロ回に。更に言うとペアのお相手は伊藤淳一さん(@jnchito)でした。

windows + ruby未インストール + rspecも知らない初心者というトリプルコンボです。目も当てられない惨状です。伊藤さん、あの時はすみませんでした。

この辺りまでが大体プログラミングを始めて2年ぐらいだったと思います。

以降、1年ほど神戸.rbに参加したり、LTをしたりしました。

アルバイト

神戸.rbに参加したり、rubyで色々書いているうちに言語仕様や標準ライブラリには詳しくなってきたある日、僕が神戸.rbの飲み会でとある方に「プログラミングのアルバイトをしたい」と言ったところ「じゃあウチで働いてみる?」と声をかけて頂きました。そこはRailsを使ってECサイトを構築し、運営する会社でした。

当時はrubyは書けるけどrailsはサッパリ分からないという状態で、まずはrails tutorialで勉強をしました。rails tutorialは良いものです。gitとrspecも同時に勉強しました。

色々思い出はあるのですが記事がドンドン長くなるので短く箇条書きにします。

  • git pushでエラーが出て、"-f付ければ?"的なメッセージが出ていたのでforce pushして怒られた
  • active_recordのベストプラクティスを知らないせいで変なこと言ってとても優秀な高専エンジニアと衝突する
  • tap + breakのコンボで高専エンジニアのコードをリファクタリング
  • プロダクトオーナーが「テストは無駄、バグを出さなければもっと早く開発が進められる」と発言して戦々恐々
  • 社長にプログラミングの難しさを説く

初めての自作PC

rubyを書くならLinuxの方が良いと思い、とりあえずファイルサーバ兼rubyプログラミング用サーバを組みました。このサーバは今も隣で元気に動いています。この前(2017年12月上旬)、OS用HDDが壊れて大変でしたが。自作PCはパーツの使い回しが効くことや、換装して修理することができるのが良いです。おまけに少しだけハードウェアについて詳しくなれます。

お金が無いのでCPUはCeleron、メモリ2GBの低スペックです。合計3万円いかないぐらいだったと思います。windowsのノートからSSHでログインしてrubyを書いていました。

デスクトップも自作PCを組んでwindows卒業したのがこの半年後ぐらいです。

アルバイトその2

いろいろあって前述のアルバイトを辞めたのですが、すぐに次のアルバイトを始めました。

今度は学習サービスを作っている会社で、僕はそこで勤怠管理用のタイムカードアプリを作りました。

結局学校の勉強が危うくなってきて、このアルバイトは泣く泣く辞めることとなりました。

この辺りでプログラミングを始めて3年半ぐらいでしょうか。

Shinosaka.rb

この時期頃からshinosaka.rbという大阪のrubyのコミュニティに参加し始めました。

rubyに限らずフロントエンドに関係する勉強会もあり、最新のWeb業界の技術に触れ、学ぶことができました。大学5年生の間は実家の山口県で薬局・病院実習をしていたため、あまり参加できていなかったのですが、これからはドシドシ参加していきたいです。

ないなら作れば良いじゃん Shinosaka.hs(Shinosaka.fp)

shinosaka.rbで「関数型の勉強会って大阪じゃあんまりないんですよね〜」と愚痴ったところ、「じゃあ自分でやれば良いじゃん」と言われ発足したコミュニティ、それがshinosaka.hsです。コミュニティの目的は「関数型言語を盛り上げること」です。

過去の発表のスライドと勉強会の反省ブログは以下です。

スライド 反省ブログ
What's Haskell? Haskell勉強会をしたことに関する反省会
Elixir入門 shinosaka.hs #2 Elixir入門を開催した
マクロ + phoenixハンズオン Shinosaka.hs #3 Elixir入門をした
関数型プログラミング基礎論 ブログなし

elixirの勉強会もしているので、shinosaka.hs(hsはhaskellの意)ではなく、shinosaka.fp(fpはfunctional programming: 関数型プログラミング)への変更を検討しています。

Elixirって良いよね

2016年の春~夏ごろに始めた言語です。「rubyと似たシンタックス関数型言語」という評判を聞きつけて始めました。shinosaka.hsでも2回、elixir関係の勉強会を開きました。

2017年にはElixir Conf Japan 2017に参加し、Elixirを現場で使っているエンジニアの方々のお話を聞き、Elixirを使っている企業への関心が高まったように思います。

Elixirに対するイメージは別のエントリで書いているため、気になる方はそちらをどうぞ。

AWSインターンシップ

インターンシップの内容を公開しても問題ない旨を担当の方が仰っていたので書きます。

当初、インターンシップに参加するつもりはあまりありませんでした。正確にはインターンシップに参加するための選考に合格できるとは思っていませんでした。

AWSクラウドサポートエンジニアのインターンシップに参加するためには技術試験と技術面接に合格する必要があります。僕はこの技術試験に興味を持ちました。「AWSの課す試験とはどういうものだろう」、そんな興味に抗えず選考を受けました。技術試験内容に言及することは避けますが、実践的なものだったとだけ述べておきます。

技術試験の結果は合格で、技術面接に進めることになりました。技術面接も実践的で、事前に提示されたテーマについて必死に情報を集めなんとか形にし、面接に挑みました。面接時点で山口で薬局実習を行っていたため、ビデオ面接という形でした。柔軟な対応がいかにも今時のIT企業という感じです。

技術面接も通過し、晴れてインターンシップに参加が決まりました。

僕が参加したのは大阪での1週間のインターンシップです。参加者は僕を含めて7人でした。皆さん、情報学部か工学部で僕だけ薬学部という非常に浮いた存在でしたが、その壁を感じることはなく、楽しくインターンシップを行えました。

初日は実践形式のトラブルシュート大会が行われました。予め問題を発生させておいたEC2サーバが用意され、問題を解決することによって点数を競うというものでした。結果は僕は4位だったと思います。AWSのEC2の設定・権限周りはもちろん、ネットワークからHTTPサーバ、果てはDBの知識まで要求される非常にレベルの高い大会でした。1位の人も全ての問題は解決できなかったようでした(しかしかなりゴールに近いところまで行っていたようでした)。

2日目以降は2, 3人のチームを組まれ、ハッカソンのようなことを行いました。僕は3人チームでした。テーマは「AWSサービスをできるだけ使い、Amazon Our Leadership Principlesを体現せよ」。僕達のチームは「議論を活性化する」ためのプロダクトを作りました。

機能としては

  • 写真から顔認識で寝ている人を発見、カウント
  • 議論の感想についての投票機能及び、円グラフによるそのビジュアライズ
  • 議論が活発かどうかの評価機能

です。

バックエンドでAWSのS3、Lambda, API Gateway, DynamoDB, Rekognitionを用いており、AWSの機能を多く使うことができたと思います。

チームの中でweb開発をしたことがあるのは僕だけで、僕はAWSについては詳しくなかったため、僕はフロントエンドをメインで担当しました。と言ってもjQueryを使ってバックエンドからデータを持ってきてChart.jsやCSSで良い感じに表示しただけなのですが。4日しかないとreactやreduxを使って作り込むのは難しいため、jQueryで妥協しました。

そういうわけでフロントエンドを作るのに大して問題はありませんでした。むしろAWSを使い慣れているメンバーがいない分、バックエンド側が大変でした。僕はバックエンドではRekognitionを用いた顔認識の処理を実装しました。Lambdaの中でrekognitionのAPIを叩くだけで様々な顔認識の結果が吐き出されて面白かったです。寝ているかどうかは顔認識の中に目を閉じているかどうかのデータを見て判断しました。目が閉じている人数を数えるだけの簡単な実装でした。APIがすごいと、物事を簡単に実現できて素晴らしいですね。

それ以外の機能もフロントエンド側からLambdaで作ったAPIを叩いてDynamoDBに保存しておき、別途フロントエンドからその情報を取得して実現しています。

チームで一緒に企画・開発するというのは楽しいですね。アルバイトはアルバイトで楽しかったのですが、企画の方には全く関わっていなかったので仕様通りに実装したり、バグを直したり、リファクタリングをするのがメインだったのでした。インターンシップではどんなものを作るのか考えながらものを作ることの楽しさを感じることができました。

最終日には各チームのプロダクトについての発表とAWSエンジニアからの評価・フィードバックと最優秀賞の発表が行われました。

ありがたいことに僕達のチームが最優秀賞を受賞しました。フィードバックには

  • UIが綺麗だった。使いやすそう
  • 技術的にもアイデア的にも素晴らしかった。可能性を感じた
  • 実装アイデアをもっとプレゼンして欲しかった
  • アプリの可能性にもう一歩踏み込んで欲しい
  • 技術的に面白かったところ
    • dynamo streamに気づいていた
    • 3チームの中で一番AWSサービスを使っていた

がありました。賞品としてfire7を戴きました。

インターンシップ中にはトラブルシュート大会とハッカソンの他にも多くのプレゼンテーションやスライド発表があり、AWSの概要や社内の雰囲気について知ることができ、貴重な体験ができたと思います。

今後

やはりITエンジニアになりたいです。特段、関数型プログラミング言語を使って仕事がしたいとは思ってはいません。もちろん使えるのであれば使いたいですが、僕が関数型プログラミングが好きな理由はむしろ「快適に綺麗なコードを書きたい」であるため、解決したい問題がオブジェクト指向や論理型プログラミング言語が適しているのであればそちらを使うべきだと思います。

「快適に綺麗なコードを書きたい」という思いがあるため、新しい技術に挑戦できることや開発環境が恵まれている、あるいは綺麗なコードが評価される文化のあるところで働きたいです。例えば関数型プログラミングであれば簡潔に書くことができる問題でも、オブジェクト指向で書くことを強制されるような社風のところでは働きたくないと感じます。より適した方法があるのであれば、それを使って問題を解決することに挑戦できるような、そんなところで働きたいです。

また、僕はプログラミングをする際に周りに人がいなかったため、OS、DBなどのミドルウェア、ネットワーク、Webバックエンド、Webフロントエンドについては独学で学んできました。それゆえ知識も浅いと思います。今後はこれらの知識も伸ばしていきたいと思うため、様々な業務をしていきたいです。

最後に

C, C++, C#, Ruby, Elixir, Haskellは文章中に登場しましたが、実はscalaも触っていたりLinuxを普段使いしていたりと全てについては書ききれていません。あと今は大学の研究室にファイルサーバを置くことになり、耐久性全振りのために生協にパーツを型番指定で注文していたりと忙しくITをエンジョイしています。

とても長いエントリになりましたが(12,000文字オーバー!)、今までのプログラミング遍歴を思い出して、「こんなこともあったなぁ」と思い出に浸ることができました。とても長い期間のことだったように感じていたのですが、書いてみると意外と短い期間で、不思議な感覚です。

今後もITに携わっていければ幸いです。

Haskellerから見たElixir

なぜこれを書いたか

案件が回ってきたので書きます。時間がないので雑な説明になります。雑すぎて公開するか悩みましたが、せっかくなので公開しておきます。先に謝っておきますごめんなさい。

自己紹介

趣味でプログラミングをやっている(ruby, railsを2年ほど書いていたのは過去の話)人です。

現在の本業は薬学部生です。平日は実習で潰れるのでここ最近全くプログラミングをしていません。

関数型プログラミングが大好きで、時間がある時期には大阪でShinosaka.hsというコミュニティで勉強会を開いています。

はじめに

一言に関数型言語と言っても多くの言語があります。「関数型言語の最右翼」とも言われている(要出典)Haskellから、ユーザーはエイリアンの見た目をしているというLisp系言語まで・・・なんかこう書くと変態しかいなさそうですね関数型プログラマって。

関数型言語が何であるのかはここでは深くは語りません。多分「ラムダ計算をベースにしている」とか「イミュータブルを基本にしている」とかそんな感じです。というか僕もよく分かっていないので誰かマサカリ投げてください。

ともかく、HaskellもElixirも一般的には関数型言語ということになっています。ナカーマ。

そんな仲間な言語であるHaskellとElixirですが、趣きは全く違います。今回はHaskellとElixirを比較したり、Elixirの特徴を挙げてみたりします。

思想の違い

ガッチガチの静的型付け言語であるHaskellに対して、Elixirは動的型付け言語です。

性質やデータを型として表現することでコンパイル時に多くのバグを発見するHaskellに対して、Elixir(Erlang)は「プログラムには必ずバグが出るものだ。全てのバグや実行時例外を把握してコードを書くことはほぼ不可能なので、エラーが出た時にどうするかを考えよう」という思想です。

具体的には処理をプロセスという実行単位に分割し、それぞれのプロセスが自分の処理だけに集中し、互いにメッセージを投げ合います。そしてどこかのプロセスがエラーで落ちるとスーパバイザという機構によって正常系に復帰します。

プロセスローカルな処理は普通にガツガツ関数で処理を書けばいいので、Haskellを書ける人ならドキュメントを見れば普通に書けると思います。

非同期なメッセージパッシングが関わる処理やプロセスデザインが肝であり鬼門です(多分)(僕もよく分かってない)。

パイプライン演算子

パイプライン演算子で処理を繋げるのも楽しいです。

# 特に意味のないコード
1..1000 # 1から1000を
|> Enum.map(fn i -> i * 2 end) # それぞれ2倍して
|> Enum.sum # 合計して
|> Integer.to_string # 文字列にして
|> String.length # 文字列の長さを出す

型システム

ElixirはHaskellほど型にこだわらないちょっと緩い感じの言語です(強い型付けではある)。一応defstructを使えば型っぽいものは作れますが、その実はただのMap型です。

defmodule Dog do
  defstruct name: "", age: 0
end

%Dog{name: "Pochi", age: 10} # %{}はMapリテラルで、%Dog{}は%{__struct__: Dog}のシンタックスシュガー

みたいにStructが作れます。ElixirにはHaskellの直和型にあたるものはありません。動的型付けなので「パターンマッチの時に適宜チェックしてやれば良い」ぐらいの感覚です。

animal = %Dog{name: "Pochi", age: 5}

case animal do
  %Dog{name: name} -> "#{name}: Bowbow,"
  %Catl{name: name} -> "#{name}: Mew."
end

型をゴリゴリ設計するHaskellerからすると物足りないかもしれませんが、データを単純な形で表現することによって難しいことを考えずにシャカシャカ書いていける感じが僕は好きです。

軽量プロセス

Elixir(Erlang)のプロセスは非常に軽量です。作られたばかりのプロセスのサイズは309 words(≒ 2.4kb)で、プロセスの起動にかかる時間はマイクロ秒レベルです。

そのためにElixirではオブジェクト指向言語インスタンスを作るのと同じくらい軽いノリでプロセスを作ります。実際にプロセスを作るコードを書いてみます。

# 1から10を出力する
1..10
|> Enum.each(fn i -># Enum.eachで1から10のそれぞれに、
  spawn(fn -> # spawnでプロセスを立てて、
    IO.puts i # 数字を出力する
  end)
end)

Haskellもスレッドを簡単に立てることができますが何万スレッドも立てるのはなかなか難しいでしょう。

2017/05/24 GHCの場合スレッドは軽量スレッドのため、数万スレッドなら普通に作れるそうです。ご指摘感謝します。 また、単純な実行速度はHaskellの方が上なので、立てることができるスレッドやプロセス数がそのままパフォーマンスの高さになるわけではないことも付記しておきます。

一方Elixirであれば100万プロセスぐらいであれば普通に動きます。5000万プロセスとかイケるみたいです。

Elixirでプロセス5000万くらい作ってみた - Qiita

Elixir(Erlang)が活きるのは高い稼働率や高い並列性(WebSocketを使うサービスやゲームサーバ)が求められるところだと思います。

アクターモデル

ざっくりと言うとオブジェクト指向のメッセージパッシングを全部非同期にしたような感じです。プロセス1つひとつをアクターと考え、互いにメッセージを非同期に投げつけ合いながら独立して動きます。

状態の持たせ方

HaskellではStateやSTやMVarやTVarやIORefなどを使って状態を持たせますが、Elixirではプロセスに持たせます。プロセス内で再帰することで状態を変えながら外部とメッセージパッシングする感じです。

マクロ

衛生的で手軽なマクロがあります。ASTを受け取ってASTを返すものです。ggればunlessの実装とかたくさん出てくると思うのでここでは説明しません(放棄

まとめ

Elixirはですね

基本的には関数型の、Erlangという言語の上で動いていまして、

若干ゃ型が、動的なところなので、

そういったところで扱いやすいように、

Elixir、あのパターンマッチで…

あとマクロも!あるので、柔軟に…構文を…作れるように、

アクターモデルぅ…ですかねぇ…(謎)

プロセスをスッと作るっことができるっ言語でして

けっこう並列処理が好きなので、

軽々と…100万プロセス5000万プロセスは余裕で動かしてくれますね(信頼)

www.nicovideo.jp

チェビシェフの不等式の証明

記事を書けばチェビシェフの不等式の証明の勉強になると思ったので書きます。案の定勉強になりましたが、予想以上に時間がかかった・・・(主にはてなブログTeXの相性の問題で)

証明のスケッチは

1. 確率分布の分散の定義
2. 確率変数の値によって2つのグループに分ける
3.  x_i - \mu >= k\sigmaの部分を置き換えて不等式にする
4.  x_i - \mu < k\sigmaの部分を捨てる
5. あとは天下り的に

今回は離散型確率分布について証明しますが、 \sum_{} \intに変えれば連続型確率分布の証明になります。



証明

前提として \sigma > 0, k > 0とする。

確率分布の分散の定義より
 {\displaystyle
\sigma^2 = \sum_{i = 0}^n (x_i - \mu)^2 P(X=x_i)
}

 x_iのうち、 |x_i - \mu| k\sigmaより大きいものと小さいものを分ける。

 {\displaystyle
\sigma^2 = \sum_{|x_i - \mu| \geq k\sigma} (x_i - \mu)^2 P(X=x_i) + \sum_{|x_i - \mu| < k\sigma} (x_i - \mu)^2) P(X=x_i)
}

ここで \sum_{|x_i - \mu| \geq k\sigma} (x_i - \mu)^2 P(X=x_i)においては |x_i - \mu| \geq k\sigmaなので、 (x_i - \mu)^2 \geq k^2\sigma^2。従って

 {\displaystyle
\sigma^2 \geq \sum_{|x_i - \mu| > k\sigma} k^2\sigma^2 P(X=x_i) + \sum_{|x_i - \mu| \leq k\sigma} (x_i - \mu)^2 P(X=x_i)
}

 \sum_{|x_i - \mu| \leq k\sigma} (x_i - \mu)^2 P(X=x_i)は正なので、引いても不等号の向きは変わらない。

 {\displaystyle
\sigma^2 \geq \sum_{|x_i - \mu| > k\sigma} k^2\sigma^2 P(X=x_i)
}

 {\displaystyle
\sigma^2 \geq k^2\sigma^2 \sum_{|x_i - \mu| > k\sigma} P(X=x_i)
}

 \sigma > 0, k > 0より、両辺を k^2\sigma^2で割って

 {\displaystyle
\frac{1}{k^2} \geq \sum_{|x_i - \mu| > k\sigma} P(X=x_i)
}

 {\displaystyle
\frac{1}{k^2} \geq P(|x_i - \mu| > k\sigma)
}

証明終わり

physmath.main.jp
physnotes.jp

関数型プログラミングに関わる本の書評

この記事はShinosaka.rb Advent Calendar 2016の19日目の記事です。

持っている本一覧

このACではrubyに限らず、どのような記事でも良いらしいので、現在僕が持っている関数型プログラミングに関係する(と思う)本の書評を書いてみようと思います。

現在持っている関数型絡みの本は

以上9冊です。

並べてみると意外と少なかったです。

現在読んでいる本は『簡約!?λカ娘 始まりの総集編』と、学校で借りた「関数型プログラミングの基礎 JavaScriptを使って学ぶ」です。

学校で借りて読んだ本は「Haskellによる並列・並行プログラミング」、立ち読みしただけなら某IQ145本もあります。

書評

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

現時点、日本語でHaskellを入門するならば第一選択です。

Haskellをやってみたい」という声が聞こえてくるとどこからともなくこの本のリンクを投げつけます。

内容はHaskellの言語仕様やHaskellで使われる概念を順番に説明していくというものです。特にファンクター、アプリカティブファンクター、モナドの説明が具体的で良いです。

ネット上であればファンクターを理解する助けになる記事はいくつかあるのですが、ファンクターのイメージををうまく説明している本はこの本ぐらいだと思います。

この本を読めば、関数の定義の仕方、型の宣言の仕方、パターンマッチ、再帰高階関数、モジュール、型クラス、入出力の基本、ファンクター、アプリカティブファンクター、モナドの辺りが分かると思います。

Haskellを始めたいならとりあえずこの本を買えばいいと思うよ!

ここだけの話、関数型界隈では「すごいH本」という愛称で呼ばれています。エッチな本。

Real World Haskell

Real World Haskell―実戦で学ぶ関数型言語プログラミング

Real World Haskell―実戦で学ぶ関数型言語プログラミング

すごいHaskellたのしく学ぼう!の後にに読むべき本だと思います。中級者向け。

特筆すべき点はその分量の多さです。なんと720ページあります。鈍器です。

実践的なコードの書き方を学ぶことができます。

すごいHaskellたのしく学ぼう!では扱っていなかったモナドトランスフォーマー正規表現やSTM、更にはParsecの使い方やデータベースの使い方(この内容は既に古くなっているかも)、果てはバーコード認識なんかも扱います。盛りだくさんです。

ところどころ内容が古くなっていて、そのまま使うのは難しい部分がありますが、現状ここまで多くのことを扱っているHaskellの日本語の本はないので更なるステップアップを望むのであれば読んで損はないと思います。

Haskellによる並列・並行プログラミング

Haskellによる並列・並行プログラミング

Haskellによる並列・並行プログラミング

この本は図書館から借りて読んだので手元にはないのですが、一応読んだ本なので紹介します。

関数型言語の触れ込みとして「並列化が得意」と言われることがありますが、その真髄を見ることができる本だと思います。

プログラミングで一般的には難しいとされる並列・並行化ですが、Haskellでは強力な抽象化能力と強力な型システムによって比較的楽に並列・並行化を行うことができます。

モナドによる抽象化は並列・並行処理でも存分に使われており、モナドの偉大さが感じられます。Evalモナド、Parモナド、STMモナド辺り。モナドなので小さな並行処理同士を組み合わせて大きな並行処理を組み立てることができます。

Evalモナドを使った並行化では、複数の式を並行に評価することで並行化を行います。

ParモナドはParallelモナドの略で名前の通り並列化を行うのですが、例えばリストのmapを並列化したりします。

STMというのはSoftware Transactional Memoryの略で、これを使うとロックフリーに並行処理を行うことができます。

この本ではEvalモナド、Parモナド、STMモナド以外にもGPUプログラミング、スレッディング、分散プログラミングも学ぶことができます。

ふつうのHaskellプログラミング

ふつうのHaskellプログラミング ふつうのプログラマのための関数型言語入門

ふつうのHaskellプログラミング ふつうのプログラマのための関数型言語入門

  • 作者: 青木峰郎,山下伸夫
  • 出版社/メーカー: SBクリエイティブ
  • 発売日: 2014/10/05
  • メディア: オンデマンド (ペーパーバック)
  • この商品を含むブログを見る

「すでに他のプログラミング言語を知っている人がサラッとHaskellの概要を覗くための本」と言ったところでしょうか。内容は「すごいHaskellたのしく学ぼう!」よりも少ないです。

基本的な言語仕様、モナドの概要を知るためであればこの本が向いていると思います。しっかりHaskellを知りたいのであれば、「すごいHaskellたのしく学ぼう!」をお勧めします。

終盤の実践的なプログラムの部分ではパーサーの作り方を知ることができるのでその点は良かったと思います。

関数プログラミング入門 ―Haskellで学ぶ原理と技法―

関数プログラミング入門 ―Haskellで学ぶ原理と技法―

関数プログラミング入門 ―Haskellで学ぶ原理と技法―

普通に証明が出てくるような本です。Haskellにおけるデータや関数の性質を確かめるために証明をします。ちょっとレベルが高いかも。僕は十分に理解はしていません。そのうち読み直したいです。

プログラミングElixir

プログラミングElixir

プログラミングElixir

現在、一般的な書店で手に入る唯一の日本語のElixir本です。

言語仕様から始まり、Elixir(Erlang)の売りであるアクターモデルの扱いを中心に説明した本です。

説明は分かりやすいと思います。アクターモデルを全く知らなかった僕ですが、この本を読んでなんとなくアクターモデルのイメージを持つことができるようになりました。

Erlangは耐障害性に重点を置いた言語で、ErlangVMの上で動くElixirもその利点を享受しています。

K10C問題やWebSocketで並行性能が注目されるようになり、ErlangVMのプロセス管理の上手さがにわかに注目を浴びましたが、Erlangの言語仕様はPrologライクでパッと見のイメージで敬遠されがちです。ElixirはRubyライクな言語仕様と極力なマクロとPhoenixというRuby on Railsインスパイアのウェブフレームワークを引っさげて登場しました。シンプルな関数型プログラミングが好きなRailsプログラマにお勧めな言語です。

エーフィーのアトリエ - アランビック錬金術

エーフィーのアトリエ - アランビックの錬金術師

Elixirの同人誌です。

内容はRails TutorialのElixir/Phoenix版と言ったところでしょうか。Ruby/RailsプログラマPhoenixを習得する最短の方法はこの本を読むことだと思っています。

エーフィーのアトリエ Plus - アランビック錬金術

エーフィーのアトリエ Plus - アランビックの錬金術師

上記の本の続編です。

内容は大きく分けてE2Eテストの方法と、Ectoの使い方です。

Scalaスケーラブルプログラミング(第2版)

Scalaスケーラブルプログラミング第2版

Scalaスケーラブルプログラミング第2版

Scalaスケーラブルプログラミング第3版

Scalaスケーラブルプログラミング第3版

いわゆる「コップ本」。

現在、第3版が出ているので今から買うのであればそちらを買った方が良いと思います。

Real World Haskellを超えるページ数を誇り、第2版の時点で744ページ、第3版は752ページあります。こちらも立派な鈍器です。

重厚な言語仕様を持つScalaをしっかりと満遍なく説明した本であり、この本を読めばScalaの基本は十分押さえたと言えるでしょう。

関数型プログラミングでよく使う、ケースクラスと型パラメータをしっかり説明してくれたのは個人的に嬉しかったです。コレクションのAPIを詳しく説明されていたのも好印象です。

ところでScalaはなぜXMLリテラルを採用したのか謎です。XMLを扱うことが最近少なくなってきていると思うのですが、Scala開発当初はそこまでXMLが流行っていたのでしょうか?

関数型プログラミングの基礎 JavaScriptを使って学ぶ

関数型プログラミングの基礎 JavaScriptを使って学ぶ

関数型プログラミングの基礎 JavaScriptを使って学ぶ

まだ読書中なので書評を書くのは憚られるのですが、パラパラと見た限りでは扱っている内容が非常に良いです。

[詳しくは読んでから書きます]

出てくるコードは基本的にJavascriptで、「Haskell怖い」という方にも良いかもしれません。

簡約!? λカ娘 - 始まりの総集編

簡約!? λカ娘 - 始まりの総集編

[読んだら書きます]

2016年12月現在、とらのあなでは売り切れており、ネット上では中古も流れていないようなので入手するのは難しいと思います。僕は運良くtwitter上で譲って頂きました。

終わりに

10冊の書評を書きましたが結構時間がかかりました。3時間ぐらい?

公式のドキュメントは英語のことが多く、ネット上にはまとまったまとまった情報が少なく、「すばやく言語を勉強したい」という時は本を読むのがベストだと思います。

特に右も左も分からない時にはまとまった情報があると非常に学習効率が良いでしょう。公式ドキュメント以外のネットの情報は最新のものや細かいものが手に入る一方、体系立った情報は手に入りにくいですし。

Shinosaka.hs #3 Elixir入門をした

やってしまった〜〜〜!!

f:id:techno_tanoC:20161127121734p:plain

やってしまいました大失態です。持ってくるノートパソコンを間違えました。

僕は現在、2台のノートパソコンを持っています。片方は中古で買ってUbuntuを入れたThinkPadで、もう一方はWindowsの入ったLenovo G510です。

普段開発用に使っているのは前者です。やっぱりLinuxでないとなかなか面倒なので。

ここまで言えばもうお察しの通り、Windowsの方を勉強会に持ってきてしまいました。一巻の終わりです。即死です。

家に取りに帰る時間も無いので、Virtualboxを入れて環境を作ろうとしたのですが、Virtualboxがエラー出て入らず詰みました。

そういうわけでちけんさんのノートの画面をプロジェクタで映しながら、口頭とSlackで説明することとなりました。ちけんさん、ありがとうございます。

そんな感じで最初からグダグダの極みだった第三回Shinosaka.hsです。

内容

今回も会場はSOU Co.,Ltd.の代表である八木さんにオフィスを貸して頂きました。ありがとうございます!

Phoenixではuse Hoge.Webを使うのでquoteぐらいのマクロの知識は必要かと思い、軽くマクロの説明をした後に、Phoenixの入門をしました。

マクロのスライドはこちらです。

phoenixの流れは↓の感じです。ソースコードこちら

  • scaffold(phoenix.gen.html)
  • 静的なページの作り方
  • json api(phoenix.jgen.json)
  • webpackとの統合(?)
  • especの導入方法

全体的にサラッとやっただけで、本格的な処理はほとんどやっていません。

みんなでワイワイできて楽しかったです。

反省

用意が足りませんでした。言い訳をすると、学校が非常に急がしかったんです・・・。今週月曜・火曜は定期試験。木曜・金曜は実習。

改善

  • Winノートは封印することにします。最近Winが必要になったのはGoでクロスコンパイルしたバイナリを試す時ぐらいでしたし、正直無くても問題ないです。

次回のShinosaka.hsでは何をしましょうか?Ectoをやりましょうか。今回はPhoenix自体の説明に終始して、Ecto周りはノータッチだったので。

shinosaka.hs #2 Elixir入門を開催した

2016年9月15日にshinosaka.hs #2としてelixir入門勉強会を行いました。

イベントページはこちら

前回のhaskell入門がアレ過ぎて、かなり凹んだのですがめげずに頑張りました。

最近はelixirが熱いということで、haskell入門を行った前回とは打って変わって、今回はelixirの入門を行いました。rubyでも並行処理が熱いですし。

場所は前回同様、SOU Co.,Ltd.の代表である八木さんにオフィスを使わせて頂きました。本当にありがとうございます。八木さんのご厚意がなければ多分shinosaka.hsは#1すら開けなかったと思います。

勉強会の冒頭には@ogomrさんにLTをしていただきました。内容はプログラミングElixirの翻訳者の1人であり、Rubyでも活躍していらっしゃる笹田耕一さんからのelixirを学ぶことについてのコメントです。今勉強している言語の本の翻訳をした方からコメントということで非常に嬉しかったです。RubyKaigi行きたかった・・・

その後は1時間30分ほどスライドを使った勉強会でした。ところどころネタが入るのは仕様です。

おおまかな内容は

です。

前回がアレだったのは内容を詰め込み過ぎたことが主な原因だったので、今回は「Hello World」「パイプ演算子」「パターンマッチ」に内容を絞ってみました。

それぞれの目的としては

elixirの特徴を語る上でerlangの話は外せないと思ったため、
「HelloWorld」はdefmoduledefIO.putsを見るため、
パイプ演算子は関数型 かつ キャッチーな言語機能を紹介したかったため、
パターンマッチはelixirを書く場合至るところで使うことになる かつ 初めて見ると戸惑いがちなものをできるだけ分かりやすく伝えたかったため、

という意図で選びました。

以下前回からの改善点、反省点、次回へ向けての改善点

前回からの改善点

  • タイポを減らすためにスライドからコードを別ファイルとして抜き出し、ちゃんと動くか試した
  • FizzBuzzとパイプ演算子とパターンマッチではrubyのコードとの対比をした
  • 前回はとにかく詰め込みすぎたので、今回はポイントを絞って内容を決めた
  • スライド中に例題を入れた
  • 次のスライドに行くのが速いので今回はスライドの一枚一枚、できるだけ説明するように意識した

反省

  • タイポ3箇所
  • パターンマッチを正規表現との半端な対比で紹介したせいであまり分かりやすくなかった
  • Elixirに対する僕の理解不足(まだあまり勉強していなかった(言い訳
  • 一枚一枚説明するように意識したけどまだ説明不足感が否めない
  • まだ説明不足感がある
  • 相変わらずテンパると早口になる。というか元々が早口

次回へ向けての改善点

  • 分かりやすいな比喩は難しい。下手な比喩は具体例を増やす方向で補う
    • 時には「これはそういうもの」という説明も必要かもしれない
  • Elixirを勉強しておく
  • もう少し例題があっても良かったかも
  • 簡易なカンペみたいなのを用意した方が良さそう。スライドに対する捕捉はカンペに書いておく
  • 落ち着け
  • 写真を撮る

次回はもうちょっと実践的な内容のElixirの勉強会をする予定です!

Elixirの同人誌(エーフィーのアトリエ - アランビックの錬金術師エーフィーのアトリエ Plus - アランビックの錬金術師)を買わなきゃ(使命感

Haskell勉強会をしたことに関する反省会

2016年7月31日にHaskellハンズオン shinosaka.hs #1を開催しました。

場所は大阪本町の株式会社ソウの代表である八木さんにオフィスを使わせて頂きました。場所がなかなか見つからず困っていたので本当にありがたいです。

勉強会の内容はHaskellの基礎ということで、関数型のベースとなっているラムダ計算、Haskellの関数定義、代数的データ型、パターンマッチでした。

以下反省点

  • スライドが少なく、最終的に1時間ほど時間が余った
  • ハンズオンと銘打った割に手を動かす部分が少なかった
  • あらゆる点で説明が少なく、参加者を置いていってしまった
  • スライドにタイポが多い
  • 説明も速く、「説明だけで終わった」という状態
  • 説明する順番が悪く、予備知識が必要な説明になっていた
  • 十分な説明もなく用語を使っていた(例えば代数的データ型でいきなり「直和型」というワードを出した)
  • slackの有効活用ができていない
  • モナド」、「型クラス」というワードを言ってしまった結果、そこの説明が必要になり、さらにグダグダに
  • 自分自身のラムダ計算の知識の不足

全体的にダメダメですね。「ハンズオンになっていない」ということが一番の問題です。最も重要な部分が達成できなかったです。

以上反省点。以下改善法

  • 具体例から入る
  • 具体例 -> 機能の説明 -> 例題という流れがあれば、スムーズかも?
  • 今回であれば(->)型の見方と関数定義の仕方とPreludeの関数の使い方をじっくり説明するぐらいが適切な分量だった
  • 別言語を使った表現でイメージしやすくする
  • 説明の順番はすごいHaskellたのしく学ぼうを参考にする
  • 『型システム入門』を初心者に勧めてはいけない
  • コンパイラを通すことでタイポを無くす

いっそのことすごいHaskellたのしく学ぼうの読書会にするというのも手ですね。下手に自分で説明するよりも本の方が分かりやすいと思います。

人に教えることの難しさを知りました。次回のshinosaka.hsは未定ですが、次回があればもっと良い勉強会にしたいです。

Rubyのcase式のたくさんの使い方(翻訳)

Ruby Case Statements with Examples

英語の練習のための翻訳

以下翻訳

if / elsif式を使うときはいつでも代わりにRubyのcase式を使うことを考慮してください。この投稿ではいくつかのユースケースと実際にどのようになっているか見てみましょう。

ノート: 他のプログラミング言語ではswitch式として知られています

Rub Case & Range

case式は初めて見た時よりももっと柔軟です。値がどの範囲に落ちるかによってメッセージを表示する例を見てみましょう。

case capacity
when 0
  "You ran out of gas."
when 1..20
  "The tank is almost empty. Quickly, find a gas station!"
when 21..70
  "You should be ok for now."
when 71..100
  "The tank is almost full."
else
  "Error: capacity has an invalid value (#{capacity})"
end

このコードはif / elsif版と比べてけっこうエレガントに見えると思います。

Ruby Case & Regex

whenの条件に正規表現を使うこともできます。以下は商品を消費するのがどのくらい危険かを知らせる最初の文字を持つserial_codeの例です。

case serial_code
when /\AC/
  "Low risk"
when /\AL/
  "Medium risk"
when /\AX/
  "High risk"
else
  "Unknown risk"
end

Ruby Caseを使わない時

単純な1対1のマッピングの時はこのように書きたくなるかもしれません。

case country
when "europe"
  "http://eu.example.com"
when "america"
  "http://us.example.com"
end

個人的には代わりにこっちの方が良いと思います。

SITES = {
  "europe"  => "http://eu.example.com",
  "america" => "http://us.example.com"
}
 
SITES[country]

ハッシュによる解決法は使う上でより効率的で簡単だと思いませんか?

===メソッドではどうなるか

あなたはcaseが内部でどう動いているか不思議に思うかもしれません。最初の例に戻ったとして、これが起こっていることです。

(1..20)   === capacity
(21..70)  === capacity
(71..100) === capacity

見ての通り、Rubyはオブジェクトを左側にして===を呼んでいるので、条件は逆転しています。===はどのクラスにも実装されているただのメソッドです。この場合、Rangeはこのメソッドをその範囲に値が見つかった時にのみtrueを返すように実装しています。

これはRubiniumでどのように(Rangeクラスに)===が実装されているかです。

def ===(value)
  include?(value)
end

ソース: https://github.com/rubinius/rubinius/blob/master/kernel/common/range.rb#L178

Procs + Case

もう一つの~===を実装している面白いクラスはProc`クラスです。

procslambdas*については来たる講座: 'Ruby Deep Dive'で学べます。 無料のレッスンを受けるにはここをクリック

この例では2つのprocsを定義し、ひとつはevenな数字か、もうひとつはoddかをチェックします。

odd  = proc(&:odd?)
even = proc(&:even?)
 
case number
when odd
  puts "Odd number"
when even
  puts "Even number"
end

これが本当に起こることです。

odd.===(number)
even.===(number)

procで===を使うことはcallを使うことと同じ効果です。

結論

あなたはRubyのcase式がどのように動き、どれほどそれが柔軟になれるかを学びました。今こそあなた自身のプロジェクトでそのベストな利用を始める番です。この記事があなたの役に立ちますように!

この投稿が多くの人が学べるようにシェアしてください。

翻訳ここまで。

今回は意訳多めにしました。句の修飾の順番が日本語と違ってなかなか正しい訳をするのは難しいです。

いまさらhaskellの状態管理に関して一言いっとくか

今回の記事はパッと出の思いつきで書いたものなのでぶっちゃけ読まないでいいです。例が面白くないです。

タイトルはそろそろFreeモナドに関して一言いっとくかパクリオマージュです。

「そろそろhaskellの状態管理に関して一言いっとくか」ではありません、「いまさら」です。要するに特に目新しいことではありません。もっと言うと状態管理というかほとんどモナドトランスフォーマーの話です。

導入

純粋関数型言語であるhaskellは「状態がないから状態管理が不得意だ」なんて言われることがあったりなかったりします。かく言う私も、昔はそんなことを思っていました。

しかし実際はhaskellはそんじょそこらのプログラミング言語よりも状態管理が得意かもしれません。少なくともある点においては明確に得意と言えるでしょう。

Stateモナド

状態と言えば英語でStatehaskellのStateモナドはその名前の通り、状態を扱うためのモナドです。

準備運動も兼ねて少し遊んでみましょう。後でStateTを使うのでControl.Monad.Trans.State.Lazyに定義してあるStateを使います。

import Control.Monad.Trans.State

addOne :: State Int ()
addOne = modify succ

doubleEven :: State Int ()
doubleEven = do
  n <- get 
  if even n
  then put $ n * 2
  else return ()
  
main :: IO ()
main = do
  print $ execState (addOne >> doubleEven) 5 -- 12
  print $ execState (doubleEven >> addOne) 5 -- 6
  print $ execState (doubleEven >> addOne) 6 -- 13

状態を裏配線して、getputmodifyで状態を更新したり取得しながら計算を行っています。

StateT

ここからが本題です。StateモナドStateモナド以上でも以下でもありません。初期値を元に計算を行って、結果を受け取る以上のことはできませんし、アプリを作る際に広い範囲で使うようなことは難しいでしょう。

そこでモナドトランスフォーマーの出番です。モナドトランスフォーマーを使えば、モナドの軛を逃れ、更なる力を得ることができます。ほぼどこでも好きなところで状態を扱えるにも関わらず、非純粋な言語のグローバル関数のようにどこでそれが使われているか分からない無秩序なものではありません。

骨組み

ある程度具体的な例を使って説明しましょう。

あなたはあるアプリケーションを作りたくなりました。そのアプリでは最初に設定ファイルから設定を読み込み、時折設定を変更しながら様々な処理をします。現時点で設定をどこかで変更したり、また別のどこかで設定を使うことは予想できていますが、プログラムの全容はまだ見えていません。

今、我々が問題としているのは設定の扱い方についてです。このプログラムが何をするかは誰も知りませんが、状態に関わる部分を作っていきましょう。

とりあえず設定を保持するStateTに加えてExceptTも使うとして、アプリ専用のモナドを構築します。

type App e s a = ExceptT e (StateT s IO) a

runApp :: App e s a -> s -> IO (Either e a, s)
runApp app s = runStateT (runExceptT app) s

evalApp :: App e s a -> s -> IO (Either e a)
evalApp app s = evalStateT (runExceptT app) s

ついでに結果だけを取り出すevalAppも作っておきました。

いろいろ

さて、今回はただの例なので扱う状態は簡単にIntということにして、このアプリで使うであろう色々な関数を書いてみます。

import Data.Char

-- 状態をインクリメントする関数
incState :: Monad m => StateT Int m ()
incState = modify succ

-- 今の状態を出力する関数
printState :: StateT Int IO ()
printState = get >>= lift . print

-- 失敗するかもしれない状態を扱う関数
doubleNonZero :: Monad m => ExceptT String (StateT Int m) ()
doubleNonZero = do
  n <- lift get
  case n of
    0 -> throwE "zero!"
    n -> lift . put $ n * 2

-- ユーザから入力を受け付ける失敗するかもしれない関数
echo :: (MonadTrans t, Monad (t IO)) => ExceptT String (t IO) ()
echo = do
  lift . lift $ putStr "type 'haskell': "
  cs <- lift . lift $ getLine
  if cs == "haskell"
    then lift . lift $ putStrLn "yes, haskell!" 
    else throwE "boo, not haskell"

-- ユーザに指示を仰ぐ失敗するかもしれない状態を扱う関数
tellNumber :: Monad m => ExceptT String (StateT Int IO) ()
tellNumber = do
    lift . lift $ putStr "tell a number: "
    s <- lift . lift $ getLine
    if isNumbers s
      then lift . put $ read s
      else throwE "not number"
  where isNumbers = all isNumber

-- ユーザをバカにする関数
fool :: IO ()
fool = putStrLn "Hey! You fool!!"

一体何に使うのか分からない関数もありますが、とりあえずこんなところでしょうか。

これらの関数は適切に持ち上げることでAppにすることができます

lift incState :: App e Int ()
lift printState :: App e Int ()
doubleNonZero :: App String Int ()
echo :: App String Int ()
tellNumber :: App Int ()
lift . lift $ fool :: App e s ()

感想

聡明な皆さんならば既にお気付きのことでしょう。これらの関数は型を見るだけでその関数が状態を扱えるかどうかが分かります。実際に型注釈にStateTが入っているincStateprintStatedoubleNonZerotellNumberは状態を扱っています。逆に型注釈にStateTが入っていないechofoolは状態を扱っていません。IOが入っているかどうかも同様です。

StateTが入っていれば必ず状態を扱うわけではないですが、確実に言えることは「StateTが入っていない関数は絶対に状態を扱えない」ということです。こうすれば実質グローバルな状態でもわざわざ使わないStateTを書かない限りはどこで状態を使っているかが一目瞭然です。変な場所で状態が変わっているかもしれない心配とはサヨナラ!

最後に

注意するべきことはこのグローバル変数を本当にグローバル変数として良いか考えることです。モナドトランスフォーマーを積み重ねすぎるとパフォーマンスに影響が出ますし、高く積もったモナドトランスフォーマーは見通しが悪く、バグの元になります。状態を扱う部分をモジュールとして切り出せないか考えるべきです。