As a part of a project I'm working on I found myself wanting to solve a 
problem, which in English would be phrased:

"Given a vector of parameterized univariate functions [f1(x1, P1), f2(x2, 
P2), f3(x3, P3), ...] with argument xj and parameters Pj, along with a 
vector of parameters [P1, P2, P3...], return a multivariate function 
g(x1,x2,x3, ...) which is the product of the parameterized input functions: 
f1(x1, P1)*f2(x2, P2)*f3(x3, P3)*..."

I decided, after some investigation, that this might be best solved by some 
metaprogramming.  I am not at all familiar with metaprogramming, so I ended 
up spending a full day trying to make this function... (don't judge me). 
 But it works!  So I'll post it as a slightly more than trivial example.

function prodFun(P::Vector, f::Vector{Function})
  ex = Expr(:call,Expr(:ref,:($f),1),:(X[1]),:($(P[1])))
  for k=2:length(f)
    exnew = Expr(:call,Expr(:ref,:($f),:($k)),:(X[$k]),:($(P[k])))
    ex = Expr(:call,:*,ex,exnew)
  end
  return eval(Expr(:(=),Expr(:call,:g,:x),ex))
end

Here's an example of it in action:

>P = {[1; 2]; [3; 4]; [5; 6]; [7; 8]}
>f(x,P) = P[1]*exp(x)/sin(P[2])
>g = prodFun(P, [f; f; f])

>g([1; 1; 1])
>>1567.0
>f(1,P[1])*f(1,P[2])*f(1,P[3])
>>1567.0

So, it works in this (and some other) test cases.

Getting to this point required a lot of fiddling around, mainly with the 
dump() function.  Along the journey, because I didn't really know what  I 
was doing, I thought maybe a macro was what I wanted. I could never get it 
to work like I wanted though.  I think the reason was because it required 
the inputs to be expressions, but I'm not super confident.  If that's the 
case, though, what's the point of macros?  You can make a function that 
accepts expression arguments and can return an expression too, but of 
course you don't have to be limited like that.  Is there an under-the-hood 
difference between a macro and a function that operates on expressions?

Reply via email to