asmeurer
asmeurer

Reputation: 91450

Why do string macros in Julia use ...?

I was looking at the source for the r_str macro in Julia, which parses r"text" into Regex("text"). The second argument is flags..., which passes flags into the regex, like i for case insensitive, and so on.

I was playing with this myself and got:

julia> macro a_str(p, flags...)
           print(flags)
           p
       end

julia> a"abc"iii
("iii",)"abc"

So it seems that the iii is all passed in as the first flag. In that case, why is there the ... on the flags. Is it possible to pass in more than one element of flags to the macro?

Upvotes: 4

Views: 1048

Answers (3)

StefanKarpinski
StefanKarpinski

Reputation: 33249

When this question was originally asked, a macro expander – i.e. the function defined with the macro keyword, which is called to transform the expressions passed to a macro into a single output expression – was not a generic function, but rather an anonymous function, which were a different kind of function in Julia 0.4 and earlier. At that point, the only way to write an anonymous function signature which could work for either one or two arguments was to use a trailing varargs argument, which is why this pattern was used to define string macros. In Julia 0.5 all functions have become generic functions, including anonymous functions and macro expanders. Thus, you can now write a macro a variety of ways, including the old way of using a varargs argument after the string argument:

# old style
macro rm_str(raw, rest...)
    remove = isempty(rest) ? "aeiouy" : rest[1]
    replace(raw, collect(remove), "")
end

# new style with two methods
macro rm_str(raw)
    replace(raw, ['a','e','i','o','u','y'], "")
end
macro rm_str(raw, remove)
    replace(raw, collect(remove), "")
end

# new style with default second argument
macro rm_str(raw, remove="aeiouy")
    replace(raw, collect(remove), "")
end

These all result in the same non-standard string literal behavior:

julia> rm"foo bar baz"
"f br bz"

julia> rm"foo bar baz"abc
"foo r z"

The string literal produces the string with the flagged letters stripped from it, defaulting to stripping out all the ASCII vowels ("aeiouy"). The new approach of using a second argument with a default is the easiest and clearest in this case, as it will be in many cases, but now you can use whichever approach is best for the circumstances.

Upvotes: 9

tholy
tholy

Reputation: 12179

With an explicit call like

@a_str("abc", "iii", "jjj")

you can pass multiple flags. But I'm not aware of a way to make this work with a"abc"ijk syntax.

Upvotes: 3

IainDunning
IainDunning

Reputation: 11644

I don't believe it is possible, and the documentation doesn't provide an example where that would be used. In addition, the mostly-fully-compliant JuliaParser.jl doesn't support multiple flags either. Perhaps open an PR on Julia changing that?

Upvotes: 2

Related Questions