前編では1.
後編である今回は、
鬼車による正規表現の強化
1.
名前を使った参照
マッチした部分文字列を、
# (?<foo>...) にマッチした部分を $~[:foo] で参照できる
if "Taro Yamada" =~ /^(?<first_name>\w+) (?<last_name>\w+)$/
p $~[:first_name] #=> "Taro"
p $~[:last_name] #=> "Yamada"
end
これによって、
また、
if /(?<first_name>\w+)\s+(?<last_name>\w+)/ =~ "Taro Yamada"
p first_name #=> "Taro"
p last_name #=> "Yamada"
end
表現能力の向上
\g<n>によって、
# かぎ括弧の対応がとれた文字列にマッチする正規表現
re = /^(\[\g<1>+\]|x)$/
p "[[x][x]]"[re] #=> "[[x][x]]"
p "[[x][x]"[re] #=> nil
p "[[x][x]]]"[re] #=> nil
また、
順序付きHash
1.
h = { "dog" => 1, "cat" => 2 }
h["panda"] = 3
h.each {|k| p k }
# 1.8の場合:順序は不定 $ ruby18 hash-order.rb ["cat", 2] ["panda", 3] ["dog", 1] # 1.9の場合:挿入した順序 $ ruby19 hash-order.rb ["dog", 1] ["cat", 2] ["panda", 3]
これによって、
プロセスの起動
system関数が拡張され、
# 環境変数ENV_VAR=childを指定して起動する
system({ "ENV_VAR" => "child" }, "echo $ENV_VAR")
# 標準出力をファイルにリダイレクトして起動する
open("log", "w") do |f|
system("echo child", out: f) # ファイルlogに"child"が書き込まれる
end
# 子プロセスを起動するだけ(子プロセスの終了を待たない)
spawn("echo child") #=> pid
環境変数や標準入出力やエラー出力以外にも、
また、
有理数と複素数が組み込みに
従来rational.
# 1/3+1/6=1/2
p Rational(1,3) + Rational(1,6) #=> (1/2)
# 虚数i*i=-1
p Complex(0,1) * Complex(0,1) #=> (-1+0i)
著者は数学クイズの解答ツールに使ったことがあります。
Kernel#pが引数を返すように
1.
# オリジナルの定義
def remove_tags(str)
str.gsub(/<[^<]+>/, "")
end
# 1.8で戻り値をデバッグ出力させる場合の変更
def remove_tags(str)
r = str.gsub(/<[^<]+>/, "")
p r
r
end
# 1.9の場合はこれだけ
def remove_tags(str)
p str.gsub(/<[^<]+>/, "")
end
1.
名前つきprintfフォーマット
printfのフォーマット文字列に名前を書き、
h = { first_name: "Taro", last_name: "Yamada", age: 30 }
p "%<last_name>s, %<first_name>s (%<age>d)" % h
"Yamada, Taro (30)"
ソースコードの可読性を上げたり、
改行の入らないbase64のエンコーディング
[string].pack("m")はstringをbase64変換する機能ですが、
puts "m:" ; puts ["a"*46].pack("m")
puts "m0:"; puts ["a"*46].pack("m0")
m: YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh YQ== m0: YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYQ==
Proc関係の増強
最後に、
Proc#===
Proc#===はProc#callのaliasです。case文のマッチが===メソッドで判定されることと組み合わせることで、
even = proc {|x| x % 2 == 0 } # 偶数なら真を返す
odd = proc {|x| x % 2 == 1 } # 奇数なら真を返す
5.times do |i|
case i
when even then puts "even!" # iが偶数の場合
when odd then puts "odd!" # iが奇数の場合
end
end
even! odd! even! odd! even!
いちいちproc呼び出しするので実行効率は悪いですが、
Proc#curry
Procをカリー化するProc#curryというメソッドが新設されました。カリー化とは、
# 2つの引数をとって和を返すProc
plus = proc {|x, y| x + y }
# Procをカリー化した Procを返す
plus = plus.curry
# 第1引数だけ適用したProcを返す
add1 = plus[1]
# 得られたProcをcallすると第2引数となり、和が計算される
p add1[42] #=> 43
まとめ
以上3回にわたって、