I’m trying to write some meta-code and I found that : operator return type is inconsistent:
> typeof(:(x)), typeof(:(1))
(Symbol,Int64)
I would expect the result of : to be always Expr, but it doesn’t seem to be true for literal expressions.
Is this by design? How do I pass literal expressions to functions that expect Expr?
In Julia, Expr
is a specific type with a head
and args
for representing ASTs. But other types can be expressions per se or part of expressions: such as symbols, and other atoms. Your function should handle these too, so it should not dispatch on Expr
only (unless that’s the intention).
1 Like
Tamas,
I understand what you are saying but this decision doesn’t make it a convenient to write meta code.
I have a data type:
immutable P
f::Expr
end
Where f will be something that will be symbolically differentiatable. (I will use rdiff). How should I change f data type in this case? Does it also mean that everywhere else I have in parameters f::Expr I have to do something else as well? Should I detect literales manually and wrap them somehow into Expr before passing to rdiff?
My advice: don’t try to force things into a uniform Expr
form. It makes meta-programming code less suited to Julia’s strengths because you can clean up Julia meta-programming code by dispatching on types rather than writing big case statements.
You can see how you could use dispatch in https://github.com/johnmyleswhite/Calculus.jl/blob/master/src/symbolic.jl. That code could even be more aggressive by adding the head symbols to the types of individual Expr
objects to distinguish them using types alone.
Anything can be an expression (or part of an expression) in Julia. Eg
julia> immutable Foo x end
julia> dump(:(x + $(Foo(9))))
Expr
head: Symbol call
args: Array{Any}((3,))
1: Symbol +
2: Symbol x
3: Foo
x: Int64 9
typ: Any
so Foo(9)
is just sitting there as an argument until +
is called, and it is not an Expr
, which :(Foo(9))
would be. (See this comment on a question I asked recently for related concepts).
More related to your application: I imagine a symbol eg :x
is also symbolically differentiable, and it is not an expression. So don’t restrict the types.
Finally, you may find this library useful: