電子書籍の厳選無料作品が豊富!

#!/usr/bin/ruby
str='hoge="abc"'
eval(str)
puts hoge

上記実行の結果エラーになってしまいますが、
evalを使って変数に代入するの方法ってあるのですか?

A 回答 (6件)

結論から言うと、#1の回答にあるようにevalの前に代入を行うという


手段をとりたくないというのであれば、方法はありません。

なぜなら、eval の引数はその中で閉じた世界になっているので、
そこで初めて出現した変数(質問の例で言えば hoge)は、evalを終えたところで
その寿命が尽きて消えてなくなるので、eval後に参照してもすでに存在していないので
エラーになるというわけです。

irb でエラーにならないのは、irb自体がRubyスクリプトであり
通常の解釈とは微妙に異なる点があるためです。

Ruby認定試験対策問題
http://projects.netlab.jp/ruby-test/index.html
Ruby認定試験対策問題 解答
http://projects.netlab.jp/ruby-test/answers.html

の、1.4.3の解説を参照してください。

何のためにそういうことをしたいのかを説明してもらえれば、代替策を
提示できるかもしれません。

この回答への補足

ご回答ありがとうございます。

>何のためにそういうことをしたいのかを説明してもらえれば、代替策を
>提示できるかもしれません。

#!/usr/bin/ruby
class Foo
def g
"g"
end
def p
"p"
end
end

f=Foo.new
str="g"
eval("ret=f.#{str}")
puts ret

上記の様に、変数strの内容によってメソッドを変える式を条件分岐文を使わずに書きたかったのですが、以下の様に書けばよいのかと。

ret=eval("f.#{str}")

ただ、この例だと、strに"g","p"以外を代入した際のキレイなエラー処理が知らなずでして。。

補足日時:2007/11/29 10:41
    • good
    • 0

ちょっとだけ改良



class Quux
def g
"g"
end

def p
"p"
end

def call(fname)
begin
method(fname).call
rescue NameError
"#{fname}なんてメソッドないじゃないですか"
end
end
end

f = Quux.new
puts "test #{f.class}"
for fnc in %w[g n p]
ret = f.call(fnc)
puts ret
end

実行例:
test Quux
g
nなんてメソッドないじゃないですか
p
    • good
    • 0
この回答へのお礼

大変参考になりました。ありがとうございます。

お礼日時:2007/11/30 13:46

きれいなエラー処理ってのが具体的にどういうものなのか


思い浮かびませんが、こんなのではどうですか?

#!/usr/bin/ruby -Ks
class Foo
def g
"g"
end
def p
"p"
end
def method_missing(arg)
"#{arg} なんて呼んでんじゃねえぞゴルァ"
end
end

class Bar
def g
"g"
end

def p
"p"
end

def call(fname)
if (@fnctable.has_key?(fname))
@fnctable[fname].call
else
"#{fname}なんてメソッドないよ"
end
end
def initialize
@fnctable = {
'p' => method(p),
'g' => method(g)
}

end
end

f = Foo.new
puts "test #{f.class}"
for fnc in %w[g n p]
ret = eval("ret=f.#{fnc}")
puts ret
end

f = Bar.new
puts "test #{f.class}"
for fnc in %w[g n p]
ret = f.call(fnc)
puts ret
end



話すと長くなりますので書きませんが、evalは乱用しない方が
いろいろ都合が良いので、できるだけ使わない方向で
考えてみるのも良いと思います。

上の、後のほうの例だと呼び出しが美しくないですけどね。
PerlとかPythonだと .call() とかつけんでもよいのですが。
    • good
    • 0

>koko_u_さん


当方の検証でも,irbではエラーが出ません。
    • good
    • 0
この回答へのお礼

検証ありがとうございます。

お礼日時:2007/11/29 10:56

やってみたけど、エラーにならんかったよ。



irb>str='hoge="abc"'

=> "hoge=\"abc\""

irb>eval str

=> "abc"

irb>puts hoge

=> "abc"

とりあえず、環境と Ruby のバージョンを補足にどうぞ。

ちなみに上の結果は windowsXP Professional で Ruby のバージョンは 1.8.6 patchlevel 0
    • good
    • 0
この回答へのお礼

検証ありがとうございます。

irbでの検証は試してみませんでした。
irbでは動作が異なる事があるんですね。

お礼日時:2007/11/29 10:55

http://pub.cozmixng.org/~the-rwiki/rw-cgi.rb?cmd …

読んでも俺には良く解らなかったけど

ruby 1.9.0 (2006-04-15)では

hoge = '';
str = 'fuga';
str='hoge="abc";';
eval(str);
puts hoge;

という風に事前に一行加えたら代入されていることが確認できた。
    • good
    • 0
この回答へのお礼

ありがとうございます。

スコープの特性ってことなんですね。

お礼日時:2007/11/29 10:54

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!