Proc.newが使えるのかな?

「cp」と「mv」とメソッド名が2文字しか違わない以下の冗長なコード。

if Options[:copy]
  Options[:events].each {|n|
    nikon.event(n).each {|photo|
      FileUtils.cp(photo[0],".",
                   {:verbose => Options[:verbose]})
    }
  }
elsif Options[:move]
  Options[:events].each {|n|
    nikon.event(n).each {|photo|
      FileUtils.mv(photo[0],".",
                   {:verbose => Options[:verbose]})
    }
  }

これをうまくまとめる方法がよく分からなかったけど、どうもProcオブジェクトというのを使えばできそうな気がする。『たのしいRuby』の索引を調べてみたら、こっそりコラムに控えめな説明がある程度だったので見落としていた。

Rubyのマニュアルによれば、

Proc はブロックをコンテキスト(ローカル変数のスコープやスタックフレーム)とともにオブジェクト化した手続きオブジェクトです。

ということで、

p = ARGV.shift.to_i
f = Proc.new {|n| n**p}

while line=gets
  n = line.to_i
  puts f.call(n)
end

ということができる。このスクリプトは引数で数字を渡すと、その数字のべき乗を返すという動きをする。Proc.newはlambdaと書いても同じようなものらしく、少なくとも上の使い方では動いた。

$ ruby test.rb 2
3
9
4
16

$ ruby test.rb 3
3
27
4
64