11月2日(土)に開催されたRuby勉強会@札幌-28に参加しました。
@niku_nameさんによるElixirについての発表と、はじめてのRuby読み合わせの2本立て。
Elixirのこと – @niku_nameさん
ElixirとはErlang(あーらん、と読む)VM上で動くプログラミング言語。
(今回はじめてききました)
Elixirには「万能薬・賢者の石・不老不死薬」という意味があるのですね。
@niku_nameさんが言っていたElixirの特徴
- すべてが式
- メタプログラミングしやすい
- マクロ機能(強力すぎてあんま使うなと公式に書いてある)
- 言語レベルでドキュメント化をサポート
- パターンマッチング(タプル)
- VM内での並列処理が容易
- VMの中で100万プロセスくらいさばける
- スレッドを作成するコストがあんまりかかっていなかった
- OTP
サンプルコードで実際の動きをいくつか見る事ができたのですが、本当にRubyっぽく書けていました。
(少し癖はありそうだとも思った)
並列実行は魅力的だなあ。
にくさんの発表は毎回肩の力が抜けていてとてもいいなあって思う。
はじめてのRuby読み合わせ
7.3.1 クロージャとしてのブロック から 7.3.3 ブロック付きメソッドの定義 まで。
yieldとかProcとか、こう、喉に魚の骨が刺さったような、わかるようでわからない感覚…
使い方はわかるのだけど自分の中でしっくり来ていないというか。
(はじめてJavaを勉強したとき、インターフェースの概念の理解に時間がかかったのと似ている感覚)
復習もかねて記録に残しておく。
7.3.1 クロージャとしてのブロック
- 関数閉包、関数オブジェクト。
- 変数の共有範囲について。
- ブロックが参照している外部環境はブロックが存在する限り保存されている。
環境の保存の例
def create_counter count = 1 return Proc.new do count +=1 p count end end #=> nil counter = create_counter #=> #<Proc:0x007fd9330808e0@(irb):28> counter.class #=> Proc counter.call 2 #=> 2 #counter.call 3 #=> 3 counter2 = create_counter #=> #<Proc:0x007fd9330481e8@(irb):28> counter2.call 2 #カウントは独立している #=> 2 counter.binding.eval("count") #Procの中の変数を評価できる #=> 3 counter2.binding.eval("count") #=> 2
Procで環境を保存するのはClassをnewするのと似ているけど、Procを使う方理由として「Classをnewするのが大げさ」「コンパクトに無名クラスを作る」「継承せずに(クラスを増やさずに)やりたい事を実現できる」というのを聞いてすっきりした。
処理の固まり(前後処理とか、ある処理の差し替えとか)が確実にわかっているときがProcの使いどころなのですね。
7.3.2 ブロック引数とブロックローカル引数
ここは大丈夫だった。
- メソッドに渡したブロックはメソッドから呼び出されるときに引数を受け取れる
- Ruby1.8と1.9では文法が少し違う => 早く1.8を卒業しましょう
- ブロック引数は外側のローカル変数とは独立している
- ブロック引数に続けて任意のブロックローカル変数を定義できる
- ブロック内が初出のローカル変数は宣言しなくてもブロックローカルになる
7.3.3 ブロック付きメソッドの定義
ここが難しかった。
- yield:メソッド内から呼び出し側のブロックをコールバックする
- yield式の値をブロック呼び出し時にブロック引数として渡す
- ブロックが与えられているかどうかは block_given? で確認できる
このサンプルでなぜ1行づつyieldが評価されるのかが理解できなかった。誰がループをまわしているの?みたいな感じで。
def foo_bar_baz yield "foo" yield "bar" yield "baz" end #=> nil foo_bar_baz do |item| puts item end "foo" "bar" "baz" #=> "baz"
さっきRubyリファレンスマニュアルを読んだら、(ブロック付きメソッドが)”与えられたブロックに最初の引数を渡して起動し、続けざまに2番目の引数を渡して起動し、さらに3番目の引数を渡して起動すること” と書いてあって少しすっきりした。
つまりこのサンプルだと、ブロック付引数が3回連続で呼び出し側をコールバックするんだ。
「コールバック」のところがしっくりきていなかったのだな。
そう考えるとこの”mapもどき”の例も「3回コールバックされ、その結果作成された配列を返す」と考えるとすっきりである。
def my_map [yield(1), yield(2), yield(3)] end #=> nil p my_map {|i| i + 1 } [2, 3, 4] #=> [2, 3, 4]
上記の例よりこっちの例の方がなるほど感があった。
erbを使うとよくyieldが出てくる。今少し調べてみたところ、この文書の流し込み処理もとても複雑である…(頭パンクする)
次回は 7.3.4 Proc から。
もっと理解を深めていきたい。
今日のメモ
Middleman
rbenvにしてからirbの日本語が文字化けしていた件
rbenv-gemset使うと幸せになれる気がする