Thank you both for the examples, those help a lot.

On Friday, April 29, 2016 at 8:57:14 AM UTC-4, Stefan Karpinski wrote:
>
> String splicing + parsing completely destroys/ignores any pre-existing 
> hierarchical structure. If you don't manually get the 
> precedence/parentheses right, it will completely break. For example:
>
> julia> a, b = "x + y", "x - z";
>
> julia> parse("$a * $b")
> :((x + y * x) - z)
>
> julia> a, b = :(x + y), :(x - z);
>
> julia> :($a * $b)
> :((x + y) * (x - z))
>
>
> The more complex the expressions you're working with, the worse this gets. 
> Similarly If there are problems with how expressions are printed, you're 
> hosed – you'll stringify some expression, splice it, parse it and get total 
> nonsense back. If you just splice expression objects, it will just work and 
> do the right thing, even for expressions which have no possible string 
> representation.
>
>
> On Thu, Apr 28, 2016 at 10:21 PM, Yichao Yu <[email protected] 
> <javascript:>> wrote:
>
>> On Thu, Apr 28, 2016 at 6:05 PM, Josh Langsfeld <[email protected] 
>> <javascript:>> wrote:
>> > 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.
>>
>> I don't believe that is true. String processing is slow, error prone
>> and unsafe. Constructing a AST using splicing is more straightforward
>> and more understandable than string splicing. Matching/processing  an
>> AST is also much easier than pattern matching and replacing in string.
>> There's good reason AST processing are not done on strings directly.
>>
>> As an example, just compare the use of parse in the code provided.
>> Note that strings are assumed to be replaced with symbols and
>> expressions since that's what should be used for AST processing.
>>
>> parse("($(reduce((a,b)->"$a,$b",args)))->$f")
>> vs
>> :(($(args...))->$f)
>>
>> fun = reduce((a,b)->"$a + $b", dfun)
>> parse("($(reduce((a,b)->"$a,$b",args)))->$fun")
>> vs
>> :(($(args...))->+($(dfun...)))
>>
>> >
>> > 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]> 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
>>
>
>

Reply via email to