Help interpolating a symbol

I am trying to make a value that does the following

var = :x1
@replace_name var = 4

I am trying to start to figure this out by doing a macro like this:

macro repname(y,body)
       body.args[1] = y
       esc(body)
end

To try and get the expression

@repname :y x = 4
> y = 4

But I can’t even do this! Only @repname y x = 4 works.

Any help in this metaprogramming problem is appreciated. Thanks.

macro repname(y,body)
    body.args[1] = ((typeof(y) == Expr) && (y.head == :quote)) ? y.args[1] : y
    esc(body)
end

julia> @repname y x = 4
4

julia> @repname :y x = 4
4

Thank you! is there any way to access the non-interned string kind of symbol other than by assembling an expression and looking at the arguments?

Any idea how to get to the last step? Of using a variable bound to a symbol to create a new variable?

That case is different, because the AST for it is equivalent to Expr(:quote, :y), which is why you cannot assign a value to it. You have to remove the quote layer to get the Symbol, to which you can assign a value.

There are a few ways you can do it but it is in general not something you should do in a macro. You need to be more specific on why you want to access a variable in the caller’s scope from a macro.

I’m trying to do something for DataFramesMeta, enabling the user to put dataframes commands inside functions.

function dotransformations(df, newvar::Symbol)
    @transfrom(newvar = 100)
end

@transform commands look like this

@transform(df, y #= no symbol, means make a new column in df =# 
          = :x1 + :x2 #= symbols reference columns of df =#). 

I want some sort of small function g() such that when DataFramesmeta examines each keyword argument, if var = :y, it replaces g(var) = :x1 + :x2 with y = :x1 + :x2. The way to do this is to inspect the expression and make a manual replacement when the expression looks like :call, :g, :var etc.

No that’s impossible. The macro cannot access any runtime variables. You need an API that allows you to provide such information at runtime or you can’t do it.

Isn’t DataFramesMeta already doing that though?

If you have a variable that is bound to a symbol, you can do the replacement _I(var) -> :y. And that works. Why is the alternative _g_(var) -> y so much different?

https://github.com/JuliaStats/DataFramesMeta.jl/blob/5d0b9b13d0755badbc82279a3acf02e99dba7330/src/DataFramesMeta.jl#L35

Well, I don’t use those so I don’t know what exactly replacement you are talking about. I’m not saying that what you want can’t be done in a different way. However, you cannot do that by translating into the @transform macro call (edit: or more specifically, the exact thing you asked about original wasn’t possible, that’s exactly why I asked what you actually want to do. Ref XY problem - Wikipedia) since AFAICT it gets the name from compile time info and your name is only available at runtime. Assuming the @transform macro is just a wrapper for DataFrame you just

In another word, they are not much different, I’m just saying you can’t use one to implement another. Both could be implementable.

1 Like