Convert to string without losing the colon character for Symbol variables

If I convert a Symbol to a string, the colon that is used to signify that it is a symbol is lost. For example,

julia> a = :abc
:abc

julia> string(a)    # String does not have a colon
"abc"

I know I can create a very simple function to preserve the colon for Symbols but not alter the string formed for other variables but I was wondering if there is already an existing function for this.

The colon is not actually part of the Symbol object, which is why you don’t get the colon when you create a String from it. Similar to how Vector is not part of the vector object itself when printing an array.

You can do ':' * string(a) to prepend the string with a colon.

There is repr:

julia> repr(:foo)
":foo"
2 Likes

It isnot a string but show(a) looks like you want

That’s not guaranteed to give you the colon, because the colon is not part of the Symbol:

julia> Symbol("1")
Symbol("1")

julia> repr(Symbol("1"))
"Symbol(\"1\")"
2 Likes

To expand a bit on what I mean when I say “the colon is not part of the symbol”; contrary to popular belief, the prefixed colon is not the “make this a symbol” operator:

julia> a = :1
1

julia> a isa Symbol
false

julia> typeof(a)
Int64

Used like this, the colon is a quasi-quote operator. This gets a bit technical, but this more or less means “give me the next fully-formed expression as the parser understands it”. For numbers, that means giving back a numeric literal, for some text that means a symbol and so on.

The issue is the following - Symbol("foo bar") is a perfectly valid symbol! You can’t produce it with :foo bar though, because the first fully formed expression after : is just foo:

julia> :foo bar
ERROR: ParseError:
# Error @ REPL[6]:1:5
:foo bar
#   └──┘ ── extra tokens after end of expression
Stacktrace:
 [1] top-level scope
   @ none:1

(thanks to @c42f for the amazing PR on the most recent master branch! It’s very useful to explain things like this).

Similarly, Symbol("1") is a perfectly valid symbol, yet you can’t get it by writing :1 because that returns an integer literal, as shown above.

So while I don’t know why you want the prefixed colon, note that it’s not part of the symbol; I’m not sure prefixing it in strings you create from a symbol is going to achieve what you’re ultimately trying to do. While repr doesn’t always give a leading : (and it can’t), it’s likely going to be what you’re looking for anyway.

2 Likes

I want to convert to a string so unfortunately show() does not work. repr() looks usable.

@Sukera: Thanks for the expanded reply. My usage is to print Dict key, value info where the key can be a Symbol like :orientation . I want the output to include the colon to alert the user that the key is a Symbol. There will not be any keys like Symbol("1") so indeed, for my purposes, repr() looks to be what I need.

1 Like

under the hood, repr calls show

julia> a=:foo
:foo

julia> sprint(show,a)
":foo"

julia> typeof(sprint(show,a))
String

@Sukera, did you mean this PR?

@rocco_sprmnt21: Interesting! If I try to use string instead of sprint I get:

julia> string(show(a))
:foo"nothing"

I do not understand this output. Can you explain this? Thanks.

As far as I understand, the show(something) function sends to the stdout (the screen) ‘something’ but returns nothing.

julia> show(a)
:foo

Introducing this as an argument to the string function produces the output of the show() function, because the argument is executed, and transforms the returned value into a string, ie “nothing”.

1 Like

No, I was referring to this one, which produced the fancy error message in the syntax error, showing that :foo is already a fully formed expression.

2 Likes