1
votes

I would like to call a macro in a Julia package (@defNLExpr in JuMP) using an argument that is runtime dependent. The argument is an expression that depends on the runtime parameter n. The only way that I can think of doing this is something like the following:

macro macro1(x)
  y=length(x.args);
  return esc(:(k=$y-1))
end

macro macro2(n)
  x="0";
  for i=1:n
    x="$x+$i"
  end
  x=parse(x);
  return :(@macro1($x))
end

n=rand(1:3)
println(n)
if (n==1)
  @macro2(1)
elseif (n==2)
  @macro2(2)
elseif (n==3)
  @macro2(3)
else
  error("expected n in 1:3")
end
println(k)

Here I have assumed that my runtime n will always be in the range 1-3. I use macro2 to build-up all possible expressions for these different possible values of n, and call the external macro (which I have replaced by the simplified macro1 here) for each of them. The calls to macro1 are in if statements, so only the correct one (determined from the value of n at runtime) will actually be executed.

Although this seems to work, is there a more efficient way of achieving this?

1
Usually runtime dependent code generation comes through @generated functions. You should check them out in the docsspencerlyon2
I believe @generated functions only have access to the type of their arguments, and so the value n would not be known.user3708067
You are right that you @generated works on types of arguments, but you can "trick" the system into working for you. If you create a type with no fields, but one type parameter n, you can then use @generated to do it. I haven't thought about your application, so I can't say I recommend this approach, but here's an example that does this. Notice that I needed d loops (d is a function argument). So I shoved that runtime value d in as the type parameter on Degree and let @generated work on Degree{d}spencerlyon2
Ugly but clever. I haven't been able to get it to work in my case yet - I think it is expanding the macro before it generates the function, so n is still just a symbol.user3708067

1 Answers

1
votes

Seems that you might be looking for eval? Be aware that it should be used with care though, and that it not very fast since it has to income the compiler each time it is called.

If it's a limitation to you that it evaluates the expression in global scope then, there are some ways to work around that.