ルビー関数の本体を文字列として持っています
s = "x + 1"
私は次のようなことをしたいと思います
fn = make_function(:x, s)
y = fn(10) # returns 11
このようなことを達成するための最良の方法は何ですか?
関数呼び出しごとに文字列を評価し続けるだけではないことに注意してください
ルビー関数の本体を文字列として持っています
s = "x + 1"
私は次のようなことをしたいと思います
fn = make_function(:x, s)
y = fn(10) # returns 11
このようなことを達成するための最良の方法は何ですか?
関数呼び出しごとに文字列を評価し続けるだけではないことに注意してください
これにより、文字列が1回評価され、関数が定義されます。
eval ['def fn(x)', s, 'end'].join("\n")
これがあなたの望むようなものですmake_function
def make_function(klass, name, args, body)
args = [ args ].flatten.map(&:to_s).join(', ')
klass.class_eval ["def #{name} (#{args})", body, 'end'].join("\n")
end
irb> make_function(Object,:foo,[:x],'x*2')
=> nil
irb> foo(10)
=> 20
irb> foo(1.3)
=> 2.6
eval
Proc
!_
def make_function(arguments, body)
eval "Proc.new { |#{arguments}
#{body}
}"
end
f = make_function :x, 'x + 1'
puts f.call 10 # 11
puts f.call 21 # 22
あなたは本当にこれをしたくありません。それにもかかわらず、それはあなたが望むように機能します。
module Kernel
def make_function(*args, string)
method_name = args.shift
parameters = args
args_string = parameters.map{|p| p.to_s}.join(",")
instance_eval <<-RUBY
def #{method_name}(#{args_string})
#{string}
end
RUBY
end
end
s = "x + 1"
make_function(:fn,:x,s)
puts fn(1) #=> 2
s2 = "x + y"
make_function(:foo,:x, :y,s2)
puts foo(1,5) #=> 2