When I have a somewhat complex datatype, I often end up constructing it by 
assigning values to local variables, then constructing a value of the 
datatype in one go at the end, like "x,y=1,2; Foo(x,y)". When there are 
many fields, Haskell's RecordWildcards idea is convenient: there you can 
say "Foo{..}", which is equivalent to "Foo(x,y)", where x, y are local 
variables. You can also decompose structures the same way: "Foo {..} = v" 
is equivalent to "x, y = v.x, v.y" (not haskell syntax). The order of 
variables is always correct, and the result is more readable, so long as 
you know what the field names are.

So in julia, it would be convenient to have macros that allow you to 
construct a type from local variables, and that allow you to inject a 
type's fields into the local environment, just like pattern matching with 
record wildcards in haskell, like so:

macro make(typename)
>   datatype = eval(typename)
>   @assert isa(datatype, DataType)
>   fields = names(datatype)
>   esc(Expr(:call, typename, fields...))
> end
> macro inject(typename, varname)
>   datatype = eval(typename)
>   @assert isa(datatype, DataType)
>   fields = names(datatype)
>   esc(Expr(:block, map(f -> :($f = $varname.$f), fields)...))
> end


An example would be

type Foo; x; y; end
> x = 1
> y = 2
> var = @make Foo
> var2 = Foo(3, 4)
> @inject Foo var2

@show x, y 


Any thoughts? The use of "eval" is slightly ugly, but the macro needs to 
know the field names of a type when it is expanded, and it cannot be a 
function because it needs to use local variables.

This is not so good for accessing fields of an external julia library, 
because you don't really know which fields are present there, but it's 
convenient when you have control over the fields yourself.

Also, how can I get a macro to evaluate an expression in the context of its 
caller? Otherwise, the "eval(typename)" is incorrect, and I don't want to 
call it as "eval(:(@inject $Foo varfoo))". The type declaration should (I 
think) already be known when the macro is expanded.

Reply via email to