第1回では、
今回は、
ブロックパラメータ(仮引数)に関する変更
ブロックパラメータのスコープがブロックローカルに
ブロック中の変数はスコープがやや曖昧でした。初出の変数の場合はブロックローカル
この問題を軽減するため、
# ローカル変数xを定義する
x = "bear"
# ブロックローカル変数xを受け取るブロック(ローカル変数のxとは別!)
["dog", "cat", "panda"].each do |x|
# このブロックの中でxの参照はブロックローカル変数の方を指す
p x
break if x == "cat"
end
# ブロックを出るとxはローカル変数の方を指すようになる
p x
# 1.8で実行した場合 $ ruby18 block-param-scope.rb "dog" "cat" "cat" # 1.9で実行した場合 $ ruby19 block-param-scope.rb "dog" "cat" "bear"
これによって、
ただしこの変更には互換性の問題があります。つまり、
$ ruby19 -w block-param-scope.rb block-param-scope.rb:5: warning: shadowing outer local variable - x "dog" "cat" "bear"
また、
foo = "bear"
# ブロックローカル変数fooを宣言する
3.times do |x; foo|
# ブロックローカル変数fooは毎回nilで初期化される
p foo #=> nil
foo = "dog"
# ブロックの終了毎にブロックローカル変数fooは消える
end
# 外側のローカル変数は変更されない
p foo #=> "bear"
ブロックとメソッドの仮引数のルールが統一
ブロックの仮引数にオプショナル引数やrest引数
def foo
yield 1, 2
yield 1
end
foo do |x, y = :default|
p [x, y]
end
[1, 2] [1, :default]
この機能はAPI設計の幅を広げると思います。また、
ただし、
実引数に関する改善
複数の実引数展開のサポート(multi split)
配列の各要素を引数としてメソッドを呼び出す記法は1.
def foo(a, b, c, d)
p [a, b, c, d]
end
ary = [1, 2]
foo(*ary, *ary) #=> [1, 2, 1, 2]
この機能は配列リテラルの中でも使えます。テーブルの作成などに便利でしょう。
p [*"0".."2", *"7".."9"] #=> ["0", "1", "2", "7", "8", "9"]
後置必須引数のサポート(post arg)
メソッド定義の仮引数では、
def foo(a, b, *ary, z)
p [a, b, ary, z]
end
foo(1, 2, 3, 4, 5) #=> [1, 2, [3, 4], 5]
この機能は、
# []=という名前のメソッドで使用すると便利
class Foo
def []=(*ary, val)
p "[#{ ary.join(",") }] <- #{ val }"
end
end
x = Foo.new
x[1] = 9 #=> "[1] <- 9"
x[1, 2] = 9 #=> "[1, 2] <- 9"
x[1, 2, 3] = 9 #=> "[1, 2, 3] <- 9"
また、
first, *, last = [1, 2, 3, 4]
p first #=> 1
p last #=> 4
その他細かい話
キーワード引数風表記
キーワード引数とは、
def set_pixel(h)
# キーワード引数はシンボルがキーのハッシュとして受け取る
@field[h[:y]][h[:x]] = h[:color]
end
# 呼び出しはキーワード引数風に
set_pixel(x:30, y:50, color:"red")
set_pixel(color:"black", x:40, y:50)
従来でもブレースのみの省略はできましたが、
例えば、
File.read("sample.txt", encoding: "UTF-8")
また、
p({dog: "bow-wow", cat: "mew"}) #=> {:dog => "bow-wow", :cat => "mew"}
改行可能な箇所の追加
Rubyは改行によって文を区切るため、
コード12 追加された改行可能箇所
# 条件演算子(いわゆる三項演算子)の:の直前
x = cond ? foo
: bar
# メソッド呼び出しのピリオドの直前
foo
.bar
.baz
ラムダ式の別記法
Rubyにはラムダ式を定義する関数lambdaがありますが、
# 1を足すクロージャを定義する(lambda {|x| x + 1 }とほぼ同義)
# '->'と'('の間にスペースを入れられないことに注意、括弧は省略可能
add_1 = ->(x) { x + 1 }
# add_1を呼び出す(add_1.call(42)の省略)
p add_1.(42) #=> 43
使うかどうかは個人の好み次第ですが、
また、
まとめ
以上のようにRuby1.
次回の後編では、