That's quite a strong statement to say never use parse. Could you explain? I think manipulating strings is typically much easier than Expr objects.
On Thursday, April 28, 2016 at 8:38:27 AM UTC-4, Yichao Yu wrote: > > > On Apr 28, 2016 7:15 AM, "Ben Lauwens" <[email protected] <javascript:>> > wrote: > > > > Hi > > > > I like to create automatically functions that evaluates the total > derivative of a function with respect to time, eg. > > given f(t, x1, x2) = t^2+x1*x2, I want to obtain > df/dt(t,x1,x2,dx1/dt,dx2/dt) = 2t+x1*dx2/dt+x2*dx1/dt, > d2f/dt2(t,x1,x2,dx1/dt,dx2/dt,d2x1/dt2,d2x2/dt) = > 2+2dx1/dt*dx2/dt+x1*d2x2/dt2+x2*d2x1/dt2, and so on. > > The initial function is specified as a string as are the arguments. > > The following code using the Calculus package works nicely: > > using Calculus > > > > function total_derivatives_with_respect_to_time(f::AbstractString, > order::Int, names::AbstractString...) > > derivs = Array(Function, order) > > n = length(names) > > args = AbstractString["t", names...] > > derivs[1] = eval(parse("($(reduce((a,b)->"$a,$b",args)))->$f")) > > if order > 1 > > fun = f > > for o = 2:order > > ∇fun = differentiate(fun, args) > > dfun = AbstractString["$(∇fun[1])"] > > for i = 1:n > > push!(args, "d$(o-1)_$(names[i])") > > end > > for j = 2:(o-1)*n+1 > > push!(dfun, "($(∇fun[j])) * $(args[j+n])") > > end > > fun = reduce((a,b)->"$a + $b", dfun) > > derivs[o] = eval(parse("($(reduce((a,b)->"$a,$b",args)))->$fun")) > > end > > end > > return derivs > > end > > > > derivs = total_derivatives_with_respect_to_time("t^2+x1*x2", 3, "x1", > "x2") > > println(derivs[1](1.0, 2.0, 3.0)) > > println(derivs[2](1.0, 2.0, 3.0, 4.0, 5.0)) > > println(derivs[3](1.0, 2.0, 3.0, 4.0, 5.0, -1.0, -2.0)) > > For calculating derivatives there may be better ways (forwarddiff and > other packages). In general, generating functions with eval is fine as long > as you dont do that in the performance critical part. However, you should > never use parse and should construct the AST directly. > > > I have however the feeling that I am abusing the sequence of eval and > parse to automatically generate anonymous function. Is there a way to do > this more elegantly? Performance wise the code runs fine in Julia v0.5. > > > > Ben >
