TL;DR: how to construct an :(a,b,c) expression from [:a,:b,:c] for use
in a macro.
Long version: I am trying to construct a macro that zips columns of
dataframes and then iterates & collects over them, eg something that
expands
@in_dataframe(df, a+b+c, 1 => a, 2 => b, 3 => c)
to
[a+b+c for (a,b,c) in zip(df[1],df[2],df[3])]
Note how indexes are values, not inferred from walking the expression,
as in DataFramesMeta. However, I want
@in_dataframe(df, a+b+c, a, b, c)
to work when column names correspond to symbols, hence the two
parse_colspec methods below.
I came up with
macro in_dataframe(df, expression, colspecs...)
function parse_colspec(e::Expr)
@assert e.head == :(=>)
varname = e.args[2]
@assert isa(varname, Symbol)
(varname,e.args[1])
end
function parse_colspec(varname::Symbol)
(varname,QuoteNode(varname))
end
dfvar = gensym("df")
vars = map(parse_colspec, colspecs)
quote
let $dfvar = $df
[$expression
for $(tuple(Symbol[v[1] for v in vars]...)) in
zip($([:($dfvar[$(v[2])]) for v in vars]...))]
end
end
end
Trying
macroexpand(:(@in_dataframe(df1, a+b+c, 1 => a, 2 => b, 3 => c)))
looks OK, except for the (:a,:b,:c) after the "for". I can't figure out
how to get (a,b,c). Other hints to improve style would also be
appreciated.
Regards,
Tamas