I am not sure what is the issue, but I would like to this to work:
julia> macro test_str(s)
:($(esc(s)))
end
@test_str (macro with 1 method)
julia> test"a 1" # "works"
"a 1"
julia> i = 1
1
julia> test"a $i" # "does not work"
"a \$i"
julia> @test_str "a $i" # works
"a 1"
interpolation happened before the string got pass to your macro.
In test"a $i", the raw string is passed to the string macro so that it can process it itself, otherwise, you won’t be able to use $ in regex r"^startend$", so it’s necessary we pass raw string to _str macros
yes, that’s what interpolation mean… that was your question right? basically the macro would see $ and you the macro author have to program the “getting the value” part
It escapes me at the moment but you can take a raw string and process it with interpolation. It’s just not common because $ is usually implemented to do something else e.g. interop code string literals convert types between languages, and we can already opt into standard string interpolation prior to a macro call this way.
I’m admittedly very limited in understanding how macros work, so I cannot solve that even for this trivial example. For instance, if I try:
julia> module TestStr
macro test_str(s)
s = replace(s, "\$i" => "$i")
:($(esc(s)))
end
end
Main.TestStr
julia> using .TestStr
julia> TestStr.test"a $i"
ERROR: LoadError: UndefVarError: `i` not defined in `Main.TestStr`
It seems that I need to know the scope from which the call to the macro is happening to interpolate that properly.
That is definitely not how I remember it, I think it had to dig into the parser. Core.eval(__module__, :i) gets you past that error at least, but it’s still not like interpolating a standard string (works with local variables).
The best way to do it manually would be to transform test"a $i" into string("a ", i) (which is what regular interpolation does). (The key thing to remember is that macros only know how things are “spelled”, not what their values are. By transforming the expression into string("a ", i) or similar, you defer the evaluation of i until the code actually executes and the value is known.)
An example of how to do this can be found in the implementation of the L"..." macro from the LaTeXStrings.jl package. In that macro, $ is treated as the beginning of a LaTeX equation, so it is left as is, but the string %$ is used for interpolation instead.
The steps are to (1) parse your string to find (unescaped) $, (2) call Meta.parseatom (or Meta.parse with greedy=false) to parse the next complete Julia expression after the $, and (3) emit the desired expression from the macro, e.g. a call to string (or the latexstring constructor in the case above).