Julia:是否可以将 `fn(df, @macro1 :a, :b, :c)` 转换为 `fn(df, (:a, :b, :c)...)`

Julia: Is it possible to transform `fn(df, @macro1 :a, :b, :c)` into `fn(df, (:a, :b, :c)...)`

例如,我想写一个宏@macro1来转换

transform(df, @macro :X :Y)

transform(df, (:X, :Y)...)

这是我的尝试

macro macro1(ex...)
    println(ex)
    :($ex...)
end

transform(df, @macro1 :X :Y)

这似乎很难。但是,如果允许宏像这样在外面

@macro transform(df, (:X :Y))

那就更简单了。但我不确定“内部”宏样式是否可以实现这一点。

我猜你想让它与逗号一起工作?

julia> macro splicing(expr)
           return Expr(:(...), esc(expr))
       end
@splicing (macro with 1 method)

julia> @macroexpand tuple(:w, @splicing :x, :y)
:(tuple(:w, (:x, :y)...))

julia> tuple(:w, @splicing :x, :y)
(:w, :x, :y)

微妙的部分是语法 @m a, b 被解析为 @m((a, b))。我们可以直接将其包装到拼接调用中。

不要尝试使用实际的可变参数,但是,可能会发生严重的堆栈溢出。

对于大小为 1 的输入,您可能需要一个特殊情况,因为这不会构造元组:

julia> tuple(:w, @splicing :x)
ERROR: MethodError: no method matching iterate(::Symbol)
Closest candidates are:
  iterate(::Core.SimpleVector) at essentials.jl:600
  iterate(::Core.SimpleVector, ::Any) at essentials.jl:600
  iterate(::ExponentialBackOff) at error.jl:218
  ...
Stacktrace:
 [1] top-level scope at REPL[34]:1

以下可能有效,但可能会变得脆弱:

macro splicing3(expr)
    if Meta.isexpr(expr, :tuple)
        return Expr(:(...), esc(expr))
    else
        return esc(expr)
    end
end