Rubyのevalっぽいこと

昨日出した問題には実は応用編も用意していた。お題はこんなの。

コマンドラインの引数から実行するメソッドの名前を受け取って、そのメソッドの計算をさせるようにしてください。

「それevalで」とか思ったけど「eval(method(array))」みたいにすると動かない。そんなことを嘆いていたらujihisaさんに教えてもらった。

require 'pp'

def sum(array)
  sum = 0
  array.each{ |i|
    sum += i.to_f
  }
  return sum.to_f
end

def mean(array)
  (sum(array)/array.size).to_f
end

def var(array)
  square = []
  (0..array.size-1).each{ |j|
    square[j] = array[j].to_f**2
  }
  var = mean(square) - mean(array)**2
  return (var*array.size/(array.size-1)).to_f
end

def hello
  puts "hello"
end

array = ARGV[1..ARGV.size-1].map{|item| item.to_f }
puts __send__(ARGV[0].intern,array)

print "Executed method was \""+ARGV[0]+"\"\.\n"

どうやらevalじゃなくって「__send__」とか「intern」、「シンボル」ってのがかぎらしい

  • 同一と同値の違い

同じ名前のシンボルは、同じオブジェクトを指しており、「同一」だといえる。
文字列はそうではなく、内容が同じ(同値)でも毎回新しいオブジェクトを生成しており、
「同値であるが同一ではない」といえる。

http://tech.x-neon.com/show/26
  • 名前付き引数のように使う
  • これはPerlにあったなあ

VBの:=な感じ。ハッシュの応用編。
メソッドを使う側もメソッド側も、意味のある名前でアクセスできるのでわかりやすくなる。
引数の組み合わせが多い場合にも便利。

http://tech.x-neon.com/show/26
def my_method(x)
  puts x[:name]
  puts x[:age]
end
my_method({:name => "ruby", :age => 32})

うむ、まだよく分かってない。シンボルとかを使うとうまくいくのは分かったけど、なんでevalでできないのかがよく分からないのであります。