2010/02/24

mdiary 最近の変更点

  5     def initialize(arg)
  6       @err = false
  7       k, @h = nil, Hash.new
  8       arg.each{|x| m = /^-(.*)/.match(x); (m) ? (k = m[1].to_sym; @h[k] = nil) : @h[k] ||= x}
  9     end


arg は ARGV の値

% .mdiary-run.rb -d 2010-01 -s music

を実行した場合 arg は

arg = ["-d", "2010-01", "-s", "music"]

になる。line 8 はこの配列を

@h = {:d=>"2010-01", :s=>"music"} 

のようなハッシュにするためのもの。

arg = ["-d", "2010-01", "-l", "3"] だった場合
@h={:d=>"2010-01", :l=>"3"}

arg = ["-d", "2010-01", "-l"] だった場合
@h={:d=>"2010-01", :l=>nil}
になる。

line 7-8 をくだいて書くと

  1 # arg = ["-d", "2010-01", "-s", "music"]
  2 k, @h = nil, Hash.new
  3 arg.each{|x| 
  4   m = /^-(.*)/.match(x)
  5   if m
  6     k = m[1].to_sym
  7     @h[k] = nil
  8   else
  9     @h[k] ||= x
 10   end
 11 } 


line 4: x が '-' で始まっていたら m の値は #<MatchData "-d" 1:"d">
line 5: m の値に何か入っていたら(マッチしたら)
line 6: k に m の1番目のマッチの値を代入。
line 7: ハッシュキーが k で 値が nil のペアを @h に格納。
line 8: m の値に何もはいっていなければ(マッチしなかったら)
line 9: @h[k] が nil の場合は x を代入。@h[k] の値が nil でなく何か値が入っていたら何もしない。

+++ memo +++

1) @h[k] ||= x

line 9 の @h[k] ||= x を @h[k] = x にしてしまうと
あやまって
arg = ["-d", "2010-01", "xxx", "-s", "music"]
が与えられてしまった時
@h = {:d=>"xxx", :s=>"music"}
になってしまう。これでは意図した結果と異なる為 ||= にしている。

2) k = nil

line 2 の k = nil を書き忘れ
line 2 は @h = Hash.new だけだった場合
arg = ["-d", "2010-01", "-s", "music"] を与えると
@h={:d=>nil, nil=>"2010-01", :s=>nil}
になってしまう。
なぜなら...
{} の外側に k が存在していなければ k は {} の中だけで使える変数となり
m == nil でなければ
k = m[1].to_sym なので k には m[1].to_sym が代入されるが

m == nil だった場合、すなわち else 節においては
k = nil が代入されてしまうから。そして
line 9: @h[k] ||= x
で nil を ハッシュキーとしたペア(nil=>"2010-01")を @h に格納することになってしまう。

だから{} の外側の k = nil はとても大切。
外側で定義された k があることによって else 節においても k は m[1].to_sym を保持していてくれる。

[2010-02-26]
arg.each{|x| m = /(^-(.*))/.match(x); (m) ? (k = m[2].to_sym; @h[k] = nil) : @h[k] ||= x}
arg.each{|x| m = /^-(.*)/.match(x); (m) ? (k = m[1].to_sym; @h[k] = nil) : @h[k] ||= x}

0 件のコメント: