user2664470
user2664470

Reputation: 801

Produce a symbol from a symbol in a macro

I'm not sure how to express this. I have a macro like so:

macro dothing(xxxx)
  # create a new symbol
  ZC_xxxx = symbol("ZC_"*string(xxxx))

  # esc so that variables are assigned in calling scope
  return esc(quote
    # assign something to the new symbol
    $ZC_xxxx = [555.0, 666.0, 777.0]

    # Store in a the dataframe
    t[:(:($ZC_xxxx))] = $ZC_xxxx
  end)
end

t = DataFrame()
@dothing(ABCD)

I want the macro to do two things: create a new variable in the calling scope, called ZC_ABCD; add a new column to the dataframe with this name and the value of the returned value. i.e. I want the expression returned from the macro to look like this:

ZC_ABCD = [555.0, 666.0, 777.0]
t[:ZC_ABCD] = ZC_ABCD

With the above show, if I add a call to show(expr) before returning it from the macro, it shows this:

ZC_ABCD = [555.0, 666.0, 777.0]
t[:ZC_xxxx] = ZC_ABCD

i.e. notice that the symbol used in the index lookup in the dataframe is not correct.

How can I achieve the desired result from the macro? What am I not understanding about symbol interpolation?

Upvotes: 1

Views: 156

Answers (1)

tholy
tholy

Reputation: 12179

Try quoting the symbol before you use it in generating an expression with the symbol:

macro dothing(xxxx)
    # create a new symbol
    ZC_xxxx = symbol("ZC_"*string(xxxx))
    q = Expr(:quote, ZC_xxxx)

    # esc so that variables are assigned in calling scope
    return esc(quote
        # assign something to the new symbol
        $ZC_xxxx = [555.0, 666.0, 777.0]

        # Store in a the dataframe
        t[$q] = $ZC_xxxx
    end)
end

That said, stylistically this kind of variable manipulation is a little dicey, because it's really hard to guess what @dothing does just by looking at the call (it references all sorts of quantities that do not appear in the @dothing(ABCD) expression).

Upvotes: 3

Related Questions