Julia Language Symbols that are not legal identifiers


Example

Julia Symbol literals must be legal identifiers. This works:

julia> :cat
: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")
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)
    Meta.quot(Symbol(str))
end

then we can simply do

julia> sym"2cat"
Symbol("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"
:test