There's still times when metaprogramming is preferable to currying, such as 
when you want to compile the resulting function for efficiency reasons. (At 
some point, we should hopefully get much of the same benefit from function 
specialization on arguments that are functions, but we're not there yet.)

I might have written your example as

using Base.Meta.quot

function prodFun(P::Vector, f::Vector{Function})
    calls = [:( $(quot(fi))(X[$i], $(quot(P[i]))) ) for (i,fi) in enumerate(
f)]
    prod  = :( *($(calls...)) )
    fun   = :( X->$prod )
    eval(fun)
end

There's a few points that I think are worth to take up:

   - It's sometimes useful to create an Expr explicitly, but it's often a 
   lot easier to use quoted code and interpolate where necessary.
   - Your implementation deferred indexing into f and P until runtime. It's 
   more efficient to extract the values when you build up the AST. I guess 
   that you did not intend that g should look up the current values in the 
   vectors f and P anyway?
   - When quoting literal values into an AST, you should always quote them 
   using Base.Meta.quot or equivalent, otherwise you might get unexpected 
   results. (Especially if the value in question is a Symbol or an Expr.)
   - You can use the multi-argument form of the * function to avoid having 
   to generate a whole chain of multiplication calls.
   - eval executes code in the global namespace, so if you do an assignment 
   (e.g. the function definition in your example), you will pollute the global 
   namespace. That is probably not what you want in this case. I've used an 
   anonymous function instead above to avoid this.

If you want to have a generic function instead of an anonymous one, you can 
use
function prodFun(P::Vector, f::Vector{Function})
    calls = [:( $(quot(fi))(X[$i], $(quot(P[i]))) ) for (i,fi) in enumerate(
f)]
    prod  = :( *($(calls...)) )
    fun   = :( let g(X) = $prod; g; end )
    eval(fun)
end


which puts the function definition in a let block so that it won't pollute 
the global scope.

Reply via email to