Could Meta.parse
grow an option to re-use $
interpolation semantics within a string macro?
I’m trying to replicate functionality of Mike Bostock’s Hyper Text Literal only ported to Julia (HypertextLiteral.jl). Specifically, our goal is to permit any sort of Julia expression, but where our string macro provides context-sensitive escaping. As an example of what we mean…
julia> htl"""<ul>$([htl"<li>$x</li>" for x in ["a", "c&d"]])</ul>"""
HTML{String}("<ul><li>a</li><li>c&d</li></ul>")
We can nest here because the outer string macro uses triple quotes, letting the inner string macro provide customized interpretation for $
. The problem is, this only works one level. While normal string interpolation works any number of levels, it doesn’t work with string macros. Let’s explain. In the trivial case of recursion, even with a regular string macro syntax, there is an immediate syntax error before the macro is even invoked.
julia> macro my_str(expr::String) expr end
@my_str (macro with 1 method)
julia> my"one$("two")"
ERROR: syntax: cannot juxtapose string literal
We can get closer by using triple quotes, at least the call gets to our macro.
julia> my"""one$("two")"""
"one\$(\"two\")"
If you use Meta.parse
for substrings marked with $
this buys you one level of nesting, however, parse
still exhibits the same limitation as above. We’ve verified this with our draft implementation. This code searches to find occurrences of $
and then uses Meta.parse
to convert this sub-expression. In particular, the opening example presented actually works.
There are work-rounds to this lack of nesting. We can use functions that return fragments. We can use let
construct. We could also implement hypertext literal as a @htl()
macro which won’t cause this issue with the grammar. Am I missing any other approach, saving clever parsing and translation that tries to emulate Julia but is otherwise brittle?
Even so. It’d be nice to have recursive interpolation for string macros. I think it’s acceptable that the outermost call would have to be triple string. However, it’d be great if subsequent usage of the string macro with single quotes could have interpolation conversion. What if Meta.parse
added an option to permit recursion in this case? Anyone could then let custom macros re-use the built-in recursive interpolation parse logic.