eval
これは役に立つ良い例だと思います。以下のコードは、指定されたものと同じ引数を取り、解決された引数のリストを吐き出すラムダを生成します。このアプローチの利点は、スプラットを解決するための Ruby 独自のアルゴリズムが使用されることです。
def resolve(parameters,args)
param_list = parameters.map do |type,name|
splat = '*' if type == :rest
"#{splat}#{name}"
end.join(',')
source = ""
source << "->(#{param_list}) do\n"
source << " res = []\n"
parameters.each do |type,name|
if type == :rest
source << " res += #{name}.map {|v| [:'#{name}',v] }\n"
else
source << " res << [:'#{name}',#{name}]\n"
end
end
source << "end"
eval(source).call(*args)
end
例:
params = ->(x,*y,z){}.parameters
resolve(params,[:one, :two, :three, :four])
#=> [[:x, :one], [:y, :two], [:y, :three], [:z, :four]]
舞台裏で、次のコードが生成されました。
->(x,*y,z) do
res = []
res << [:'x',x]
res += y.map {|v| [:'y',v] }
res << [:'z',z]
end
2 つの引数を持つ別の例、最初にスプラ:
params = ->(*x,y){}.parameters
resolve(params,[:one, :two, :three, :four])
#=> [[:x, :one], [:x, :two], [:x, :three], [:y, :four]]
生成されたコードは
->(*x,y) do
res = []
res += x.map {|v| [:'x',v] }
res << [:'y',y]
end