せかいや

いまいるここを、おもしろく http://sekai-in-the-box.appspot.com/

【Ruby】パーフェクトRuby 学習感想文 ~余談:制御構造を理解する

Rubyの制御構造を確認する。
http://doc.ruby-lang.org/ja/1.9.3/doc/spec=2fcontrol.html


(参考・経緯など)
パーフェクトRuby 学習感想文 ~はじめに


あわせて、苦手な3章をもう一度読み返す。。

 

ブロックとループでは変数のスコープが違う

do ... endまたは{ }による ブロックは新しいローカル変数の有効範囲を導入するのに対し、 for文はローカル変数のスコープに影響を及ぼさない点が 異なるからです。

http://doc.ruby-lang.org/ja/1.9.3/doc/spec=2fcontrol.html

 
 
確認してみる↓

for i in [1, 2, 3]
	aa = "hoge1"
end
[1,2,3].each do |i|
	bb = "hoge2"
end
p aa
p bb

■実行結果

"hoge1"
`<main>': undefined local variable or method `bb' for main:Object

これは何でかと言うと、ブロックは結局引数なので、
その引数が渡されたメソッド(今の例ではeach)の中でしか参照できないから。
ブロックの自作で勉強した⇒ http://sekai.hateblo.jp/entry/2013/08/24/094939


 

イテレーターの自作

for や each で配列要素を複数個ずつ取得しながらループすることは できません。
代わりにそのようなメソッド(イテレータ)を定義する必要があります。

実装してみる。

class Array
  def each2
    i = 0
    while i < self.size
      yield self[i], self[i+1]
      i += 2
    end
  end
end

[1, 2, 3].each2 do |i, j|
  p [i,j]
end

■実装結果

[1, 2]
[3, nil]

ブロックの考え方が分かってたらできる。


 

公式のまちがい

def iter(var = p("(a)"))
  p " : "
  yield
  p "(c)"
  p " : "
ensure
  p "(d)"
end
iter { p "(b)"; redo  }     # => (a) .. (b)(b)(b)(b) ...
iter { p "(b)"; next  }     # => (a) .. (b)(c) .. (d)
iter { p "(b)"; break }     # => (a)..(b)(d)

■実行結果

"(a)"
" : "
"(b)"
"(c)"
" : "
"(d)"

あはー。セミコロンがおねんねしてるよ。
せっかくなので公式(るりまプロジェクト)のバグ報告から報告しておく。
http://bugs.ruby-lang.org/issues/8824

 

returnに複数の値

式の値を戻り値としてメソッドの実行を終了します。式が2つ以上 与えられた時には、それらを要素とする配列をメソッドの戻り値と します。式が省略された場合には nil を戻り値とします。

http://doc.ruby-lang.org/ja/1.9.3/doc/spec=2fcontrol.html#return
def hoge
return 10,20
end
p hoge

■実行結果

[10, 20]

ほんとや。配列や。


制御構造は使って慣れて、っていうのも大事だと思う。。
頑張るよ。。