Hi there,
I am experimenting a bit with macros and wanted to know wheter there is a way to interpolate a variable (that is local to the macro) value inside a string within an expression returned by the macro.
a MWE is like the following
macro test1()
a = "magic"
:("This is $a")
end
Now I would like @macroexpand @test1
to return :("This is magic")
, but instead it returns :("This is $(Main.a)")
.
I know that for this very simple example I could just create the :string
Expression directly but my actual use case is more complicated.
What I am doing is probably convoluted/wrong but basically I have something similar to this;
using HypertextLiteral
macro testt()
a = "randomstring"
:(@htl """
<- HTML things before ->
<script>
console.log($a)
// JS things after
</script>
""")
end
Building the resulting @htl
expression by hand becomes quite complicated so I wanted to ask if there is a easier way to make the interpolation of variable inside strings inside expression work as I want.
While not directly answering your question … one thing you are missing is called hygene,
macro test1()
quote begin
a = "magic"
b = "This is $a."
return b
end; end
end
julia> @test1()
"This is magic."
With macros, It is good practice to use quote ... end
or :( ... )
which is shorthand and appropriate for e.g. single line macro definitions. Omitting the quote
block may allow unexpected scoping mixups to arise.
typeof( :("this string") ) == String
,
:("this")
is the same as "this"
, so it is not clear what you want here.
Yeah, the MWE is not super helpful to understand here.
What I wanted to achieve specifically is a bit convoluted and I don’t think is entirely necessary for the purpose of this question, which is understanding the general behavior of interpolation within strings within macros.
Let me reformulate an example, in my view there could be three possible ways of interpreting the interpolation, and I put them in the example macro below:
macro test2(sym::Symbol)
a = "Local"
esc(quote
s1 = "Case 1: Interpolate the local variable directly in the string: $a"
s2 = "Case 2: Leave the string interpolation as it is written: $b"
s3 = "Case 3: Use the symbol given to the macro: $sym"
end)
end
The output of @macroexpand
on that is below, where I removed the LineNums and added as comments what I would like to be able to achieve for these 3 cases
julia> @macroexpand @test2(c)
quote
# I would this to be
# s1 = "Case 1: Interpolate the local variable directly in the string: Local"
s1 = "Case 1: Interpolate the local variable directly in the string: $(a)"
# This case is exactly as it should be
s2 = "Case 2: Leave the string interpolation as it is written: $(b)"
# I would this to be
# s3 = "Case 3: Use the symbol given to the macro: $(c)"
s3 = "Case 3: Use the symbol given to the macro: $(sym)"
end
Is there some way to get the different behavior when doing interpolation inside string within expressions?
With the synthax as above all the 3 lines are using the interpolation of case 2
Edit:
My impression is that the only way to achieve the behavior of Case 1 and Case 3 is to construct the specific expression by hand using Expr
, but I hope there might be something easier I don’t know about