1

我有一个红宝石函数的主体作为一个字符串

s = "x + 1"

我想做类似的事情

fn = make_function(:x, s)
y = fn(10) # returns 11

实现这样的目标的最佳方法是什么?

请注意,我宁愿不只是继续评估每个函数调用的字符串

4

3 回答 3

2

这将评估字符串一次以定义函数。

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
于 2012-10-14T01:05:13.587 回答
0

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
于 2012-10-14T01:07:38.240 回答
0

你真的不想这样做。但是它仍然可以按您的意愿工作。

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
于 2012-10-15T20:20:50.033 回答