Julia Language String Macros


  • macro"string" # short, string macro form
  • @macro_str "string" # long, regular macro form
  • macro`command`


String macros are not quite as powerful as plain old strings — because interpolation must be implemented in the macro's logic, string macros are unable to contain string literals of the same delimiter for interpolation.

For instance, although

julia> "$("x")"

works, the string macro text form

julia> doc"$("x")"
ERROR: KeyError: key :x not found

gets parsed incorrectly. This can be somewhat mitigated by using triple-quotes as the outer string delimiter;

julia> doc"""$("x")"""

does indeed work properly.

Using string macros

String macros are syntactic sugar for certain macro invocations. The parser expands syntax like

mymacro"my string"


@mymacro_str "my string"

which then, like any other macro call, gets substituted with whatever expression the @mymacro_str macro returns. Base Julia comes with several string macros, such as:


This string macro constructs byte arrays instead of strings. The contents of the string, encoded as UTF-8, will be used as the array of bytes. This can be useful for interfacing with low-level APIs, many of which work with byte arrays instead of strings.

julia> b"Hello World!"
12-element Array{UInt8,1}:


This macro will return a BigInt or a BigFloat parsed from the string it's given.

julia> big"1"

julia> big"1.0"

This macro exists because big(0.1) does not behave as one might initially expect: the 0.1 is a Float64 approximation of true 0.1 (1//10), and promoting that to BigFloat will keep the approximation error of Float64. Using the macro will parse 0.1 directly to a BigFloat, reducing the approximation error.

julia> big(0.1)

julia> big"0.1"


This string macro constructs Base.Markdown.MD objects, which are used in the internal documentation system to provide rich-text documentation for any environment. These MD objects render well in a terminal:

terminal markdown documentation renders well

and also in a browser:

browser markdown documentation renders well


This string macro constructs HTML string literals, which render nicely in a browser:

html string macro rendering nicely in a browser


This string macro constructs IP address literals. It works with both IPv4 and IPv6:

julia> ip""

julia> ip"::"


This string macro constructs Regex literals.


This string macro constructs SubstitutionString literals, which work together with Regex literals to allow more advanced textual substitution.


This string macro is similar in spirit to @doc_str and @html_str, but does not have any fancy formatting features:

plain text in the browser


This string macro constructs VersionNumber literals. See Version Numbers for a description of what they are and how to use them.


This string macro constructs the singleton types of MIME types. For instance, MIME"text/plain" is the type of MIME("text/plain").

Julia Symbol literals must be legal identifiers. This works:

julia> :cat

But this does not:

julia> :2cat
ERROR: MethodError: no method matching *(::Int64, ::Base.#cat)
Closest candidates are:
  *(::Any, ::Any, ::Any, ::Any...) at operators.jl:288
  *{T<:Union{Int128,Int16,Int32,Int64,Int8,UInt128,UInt16,UInt32,UInt64,UInt8}}(::T<:Union{Int128,Int16,Int32,Int64,Int8,UInt128,UInt16,UInt32,UInt64,UInt8}, ::T<:Union{Int128,Int16,Int32,Int64,Int8,UInt128,UInt16,UInt32,UInt64,UInt8}) at int.jl:33
  *(::Real, ::Complex{Bool}) at complex.jl:180

What looks like a symbol literal here is actually being parsed as an implicit multiplication of :2 (which is just 2) and the function cat, which obviously does not work.

We can use

julia> Symbol("2cat")

to work around the issue.

A string macro could help to make this more terse. If we define the @sym_str macro:

macro sym_str(str)

then we can simply do

julia> sym"2cat"

to create symbols which are not valid Julia identifiers.

Of course, these techniques can also create symbols that are valid Julia identifiers. For example,

julia> sym"test"

Implementing interpolation in a string macro

String macros do not come with built-in interpolation facilities. However, it is possible to manually implement this functionality. Note that it is not possible to embed without escaping string literals that have the same delimiter as the surrounding string macro; that is, although """ $("x") """ is possible, " $("x") " is not. Instead, this must be escaped as " $(\"x\") ". See the remarks section for more details about this limitation.

There are two approaches to implementing interpolation manually: implement parsing manually, or get Julia to do the parsing. The first approach is more flexible, but the second approach is easier.

Manual parsing

macro interp_str(s)
    components = []
    buf = IOBuffer(s)
    while !eof(buf)
        push!(components, rstrip(readuntil(buf, '$'), '$'))
        if !eof(buf)
            push!(components, parse(buf; greedy=false))
        string($(map(esc, components)...))

Julia parsing

macro e_str(s)

This method escapes the string (but note that escape_string does not escape the $ signs) and passes it back to Julia's parser to parse. Escaping the string is necessary to ensure that " and \ do not affect the string's parsing. The resulting expression is a :string expression, which can be examined and decomposed for macro purposes.

Command macros


In Julia v0.6 and later, command macros are supported in addition to regular string macros. A command macro invocation like


gets parsed as the macro call

@mymacro_cmd "xyz"

Note that this is similar to string macros, except with _cmd instead of _str.

We typically use command macros for code, which in many languages frequently contains " but rarely contains `. For instance, it is fairly straightforward to reimplement a simple version of quasiquoting using command macros:

macro julia_cmd(s)

We can use this macro either inline:

julia> julia`1+1`
:(1 + 1)

julia> julia`hypot2(x,y)=x^2+y^2`
:(hypot2(x,y) = begin  # none, line 1:
            x ^ 2 + y ^ 2

or multiline:

julia> julia```
       function hello()
           println("Hello, World!")
:(function hello() # none, line 2:
        println("Hello, World!")

Interpolation using $ is supported:

julia> x = 2

julia> julia`1 + $x`
:(1 + 2)

but the version given here only allows one expression:

julia> julia```
       x = 2
       y = 3
ERROR: ParseError("extra token after end of expression")

However, extending it to handle multiple expressions is not difficult.