ひがきの日記

2013-02-02

Ruby初級者向けレッスン 44回 ― ブロック ―

第56回 Ruby/Rails勉強会@関西での初級者向けレッスンのスライドを公開します。*1

f:id:mas-higa:20130205231822p:image

繰り返し

a = [0, 1, 2]

a.each do |i|
  puts i
end

a.each{|i| puts i}

# >> 0
# >> 1
# >> 2

f:id:mas-higa:20130204232616p:image

  • ブロックの代表的な使い方は繰り返し処理。
  • do と end で囲まれたもの、{ と } で囲まれたものがブロック。
    • 上のコードと下のコードは同じ処理をしている。
  • Array のように、たくさんのオブジェクトを持っていると、全てのオブジェクトに繰り返し同じ処理をしたいことがよくある。
  • | と | で囲まれた変数 i が Array の各要素を順に指す。

便利な例

a = [0, 1, 2, 3]        # => [0, 1, 2, 3]

a.map{|i| i * i}        # => [0, 1, 4, 9]
a.select{|i| i.even?}   # => [0, 2]
a.inject{|s, i| s + i}  # => 6
a.find{|i| i.odd?}      # => 1
a.all?{|i| i.even?}     # => false
a.any?{|i| i.even?}     # => true

f:id:mas-higa:20130204232617p:image

  • 初級者には、このスライドがおすすめ。

f:id:mas-higa:20130204232620p:image


ブロックを渡す

  • メソッドには、ブロックをひとつ渡せる。
  • ブロックをどう使うかは、メソッド次第。
    • 繰り返し
    • ハリウッドの原理
open('hello.txt')   # => #<File:hello.txt>
open('hello.txt'){|f| f.read}
                    # => "こんにちは\n"

f:id:mas-higa:20130204232618p:image

  • ブロックの役割りは、繰り返しだけではない。
  • ブロックの有無で動作を変えるメソッドがある。

ハリウッドの原理

# open('hello.txt'){|f| f.read}

begin
  f = open('hello.txt')
  f.read
ensure
  f.close unless f.nil?
end

f:id:mas-higa:20130204232619p:image

  • 処理のスケルトンメソッドで用意しておき、処理の一部をブロックで切り替える。
  • ブロック付きの 1行で書いた open メソッドは、ブロックなしで書くと、だいたいこんな感じ。
  • close の部分は f.close unless f.closed? かも。

ブロックのない open

f:id:mas-higa:20130206000309p:image

  • ファイルを扱う場合は、以下の処理が必要。
    1. open
    2. read/write など
    3. close
  • コードを書く際の負担が多い。

ブロック付き open

f:id:mas-higa:20130206000308p:image

  • open メソッドが忘れずに close してくれる。
  • コードを書く際の負担が少ない。

値を受け取る

f:id:mas-higa:20130204232621p:image


値を受け取る (2)

  • 受け取るか受け取らないかは、ブロック次第。
2.times{puts 'こんにちは'}
# >> こんにちは
# >> こんにちは

2.times{|i| puts i}
# >> 0
# >> 1

f:id:mas-higa:20130204232622p:image

  • 上の例は値を受け取っていない。
  • しかし times メソッドは値を渡してくれる。(下の例)
  • ブロックは必ずしも値を受け取る必要はない。

Hash の例

people = {matz: 47, dhh: 32}
            # => {:matz=>47, :dhh=>32}

people.each{|person| p person}
# >> [:matz, 47]
# >> [:dhh, 32]

f:id:mas-higa:20130204232623p:image

  • key と value のペアを受け取れる。
  • ふたつの値が、ひとつの Array オブジェクトに。

Hash の例 (2)

people = {matz: 47, dhh: 32}

people.each do |name, age|
  p "#{name}(#{age})"
end

# >> "matz(47)"
# >> "dhh(32)"

f:id:mas-higa:20130204232624p:image

  • ふたつの値を、それぞれ別の変数で受け取れる。
  • | と | の間に , で区切って変数を列挙する。

each_cons の例

midosuji = ["梅田", "淀屋橋", "本町", "心斎橋", "なんば"]

midosuji.each_cons(2){|path| p path}

# >> ["梅田", "淀屋橋"]
# >> ["淀屋橋", "本町"]
# >> ["本町", "心斎橋"]
# >> ["心斎橋", "なんば"]

f:id:mas-higa:20130204232625p:image


each_cons の例 (2)

midosuji.each_cons(2) do |from, to|
  p "#{from} - #{to}"
end

# >> "梅田 - 淀屋橋"
# >> "淀屋橋 - 本町"
# >> "本町 - 心斎橋"
# >> "心斎橋 - なんば"

f:id:mas-higa:20130204232626p:image

  • ふたつの値を、ふたつの変数で受け取る。

each_cons の例 (3)

a = [*0..3]     # => [0, 1, 2, 3]

a.each_cons(3){|i| p i}
# >> [0, 1, 2]
# >> [1, 2, 3]

a.each_cons(3){|i, j| p [i, j]}
# >> [0, 1]
# >> [1, 2]

f:id:mas-higa:20130204232627p:image

  • 繰り返しの回数は、どちらも 2回。
  • みっつの値を、ひとつの変数で受け取ると Array オブジェクトになる。(上)
  • みっつの値を、ふたつの変数で受け取ると、みっつ目の値が受け取れない。(下)

おかしいな? と思ったら

p unknowns.first
            # >> [1, ["matz", 47]]

unknowns.each do |id, (name, age)|
  id        # => 1
  name      # => "matz"
  age       # => 47
end

f:id:mas-higa:20130204232628p:image

  • 要素を、ひとつ取り出して見る。
  • 例えば、こんなふうに表示されたら、値は幾つか?
    • 答えは、ふたつ! *2
      1. 数値 (1)
      2. Array
        • 中身は、文字列 ("matz') と数値 (47)
  • みっつの変数で受け取るには Array の中の Array を ( ) で表記する。

ブロックを受け取るメソッド

  • こんな感じで呼びたい
monta{puts 'block!'}

# >> block!
# >> block!
# >> 大切なことなので

f:id:mas-higa:20130204232629p:image

  • monta というメソッドを作る。
    • ブロックを 2回評価して、
    • 最後に '大切なことなので' と出力する。

ブロックを受け取る方法は、ふたつある。


ブロックを受け取る

def monta
  yield
  yield
  puts '大切なことなので'
end

f:id:mas-higa:20130204232630p:image

  • yield メソッドで受け取ったブロックを評価する。

ブロックを受け取る (2)

def monta &block
  block.call
  block.call
  puts '大切なことなので'
end

f:id:mas-higa:20130204232631p:image

  • 引数でブロックを受け取る。
  • call メソッドでブロックを評価する。

値を渡す

  • monta メソッドの仕様を変更。
  • ブロックに '大切なことなので' という文字列を渡す。
def monta
  yield '大切なことなので'
  yield '大切なことなので'
end

monta{|i| puts "#{i} block!"}

# >> 大切なことなので block!
# >> 大切なことなので block!

f:id:mas-higa:20130204232632p:image

  • yield メソッドに文字列を渡すだけの簡単なお仕事です。

値を渡す (2)

  • また monta メソッドの仕様を変更。
  • ブロックに '大切な', 'ことなので' という、ふたつの文字列を渡す。
def monta &block
  block.call '大切な', 'ことなので'
  block.call ['大切な', 'ことなので']
end

monta{|i| puts "#{i} block!"}

# >> 大切な block!
# >> ["大切な", "ことなので"] block!

f:id:mas-higa:20130204232633p:image

  • block.call に、ふたつの文字列を渡すだけだと……
    • ブロックがひとつの変数で待ち受けていると、ふたつ目の文字列が受け取ってもらえない。
  • ふたつ以上の値を渡すときは、Array のオブジェクトにして渡す。

ブロックは Proc

block = Proc.new do |i, j|
  puts "#{i}#{j} block!"
end

monta &block

# >> 大切なことなので block!
# >> 大切なことなので block!

f:id:mas-higa:20130204232634p:image

  • あらかじめブロックだけ生成しておける。
  • メソッドに渡す際には & を付ける。

Q&A

Q1
ブロックをふたつ渡せないの?
A1
& なしで普通の引数としてなら渡せます。
Q2
さっきから EmacsRuby のコード実行してるけど、それなに?
A2
るびきちさんが作られた rcodetools を使ってます。Ruby を起動して実行結果を # => の後に埋め込んでくれます。(コード補完もできます) コメントなので、結果の埋め込まれたコードは、そのまま保存・実行できます。
Q3
どんなキーバインドなの?
A3
えっ、それ重要?

*1:スライドだけ欲しい人は直接どうぞ http://higaki-it.jp/ruby/56/slide.pdf

*2:こんなデータ構造が Array で渡ってきたら、データ構造の設計が間違ってる。

2011-04-10

るびきちさんを囲む会

るびきちさんが関西にいらっしゃるというので kansai-emacs #x03 開催が決まったようだ。

勉強会については他の人にお任せするとして、午後からの勉強会に先立って午前中に行われた会合についてレポートしてみる。

朝 9:30 になんばマルイ前でるびきちさんと待ち合わせ。
普段はリア充がイチャつく待ち合わせスポット。
まさかこの場所で待ち合わせすることになるとは。*1

集まると早速 Emacs を起動する人たち。

街中でも Emacs!

その後は観光 …… のはずが、時間が早くてお店も開いてない。
午後からは京都勉強会なので遠くへ行くこともできず。*2

人気のない心斎橋をブラブラして終了。

るびきちさんはスケジュールの都合で京都には行けないらしい。残念。
次の機会にはぜひ勉強会にも参加していただきたい。*3

関西Emacs勉強会だというのに空気を読まずに Ruby の本ばかり持参してサインをいただいた!

るびきちさんの Ruby本といえばコレ!

Ruby逆引きハンドブック

Ruby逆引きハンドブック

なつかしの 256本

Rubyを256倍使うための本 魔道編

Rubyを256倍使うための本 魔道編

ちゃんと Emacs の本もありますよ (違)

Rubyシェルプログラミング

Rubyシェルプログラミング

すみません。Emacs テクニックバイブル 持ってこなくて すみません。

*1:朝早いこともあってリア充はいなかった。

*2:結局遅刻しました。すみません。

*3Ruby関西にも来ていただきたいものです!

2009-11-22

Genius bar の使い方

Apple 製品の具合が悪くなったら Apple store 内の Genius bar へ持って行くと故障の診断、修理、交換などしてくれる。

Genius bar を使うには若干のコツがいる。

とりあえず予約

昔とちがって数日前から予約ができるようになった。
最寄りの Apple store の Genius bar の予約を取ろう。

名前にニックネーム (ハンドルネーム) などを使うと、いたずらと判断されて予約が無効になることがある。
来店時にコンシュルジュ (店員さん) にニックネームで予約したことを告げれば大丈夫。

予約がいっぱいでも諦めてはいけない。
当日の朝に再チャレンジすると予約できることがある。*1

早めに店に行こう

手の空いた Genius が予約者 5 〜 6 名くらいをいっぺんに呼び出す。
その時に他の予約者がいなければ、予約時間前でも対応してもらえる。

何度か心斎橋の Genius bar を利用した経験では、早めに行っても、ほぼ入店直後に対応してもらえた。

説明は Apple の用語で

ifconfig で …… とか、fsck が …… とか言っても相手にされない。*2

Unix 的に現象を把握できても、それを Mac 純正ツールで認識できるようにならないと対応してもらえない。
コマンドラインやオープンソースソフトウェアなどではなく Mac 純正ツールで再現できるようにしておくこと。

予約時に Apple 用語で説明しておくと対応も早い。

まとめ

近くに Apple store があるなら Genius bar を活用すべき。

非常に親切に対応してもらえる。

しかも Genius にはイケメンが多い。*3

*1:当日枠があるのか?

*2:昔 Ethereal のログを見せて「この通信は何ですか?」と質問してドン引きされた。

*3:女性 Genius に対応してもらったことがないのが残念だ。