:"@=".inspect is non-evaluatable
There is an edge case where
Symbol#inspect returns a non-evaluatable expression:
:"@=".inspect # => :@= :"=".inspect # => := :"$$$$=" # => :$$$$=
More specifically, the quotations are stripped if the following conditions are met (but the converse does not hold):
- It starts with
- the prefix is not followed by an identifier, and
- it ends with
But the rule should only apply to
:=, because (in my understanding) we should generally have
eval(sym.inspect) == sym for the programmers' convenience.
Updated by sawa (Tsuyoshi Sawada) about 1 year ago
Not sure what you mean.
inspect is expected to return a string, and the cases you mention indeed return a string respectively.
:"@=".inspect #=> ":@=" :"=".inspect #=> ":\"=\"" :"$$$$=".inspect #=> ":$$$$="
However, among them,
:"$$$$=".inspect do not include quotations. Is that what you are at?
Updated by qnighy (Masaki Hara) about 1 year ago
sawa (Tsuyoshi Sawada) wrote in #note-1:
However, among them,
:"$$$$=".inspectdo not include quotations. Is that what you are at?
Ah yes, the second example is my mistake. It should have been
:"[=]=" or such. I think these symbols are better quoted than not.
nobu (Nobuyoshi Nakada) wrote in #note-2:
inspectmethods are not for
We only guarantee that
sym.name.to_sym == sym.
I understand it is not a guarantee and thus this is a relatively subtle issue. Nonetheless I think the behavior is not an intended one because Ruby values (including symbols) often implement
#inspect in a way it is evaluatable.
Let me give more context on it: I was implementing the
parser gem's AST serialization in another language to use the gem as a reference implementation. Under the hood it uses
Symbol#inspect to stringify symbols and thus I was interested in the
Updated by ufuk (Ufuk Kayserilioglu) about 1 year ago
I was bitten by the same thing last week and was actually going to open an issue myself. Thanks for raising this @qnighy (Masaki Hara).
The thing that caught me out was that the following discrepancy:
"4_to_5".to_sym.inspect #=> :"4_to_5" "4_to_5=".to_sym.inspect #=> :4_to_5=
I realize that Ruby spends a considerable amount of effort to not print symbols in a format where they could not be roundtripped, and the discprancy between
:"4_to_5=" was surprising.
I bisected the change to the released versions of Ruby and found that the behaviour changed somewhere between
$ docker run --rm -e "ALL_RUBY_SINCE=ruby-2.0" rubylang/all-ruby ./all-ruby -e "puts '4_to_5='.to_sym.inspect" ruby-2.0.0-p0 :"4_to_5=" ... ruby-2.2.0-preview1 :"4_to_5=" ruby-2.2.0-preview2 :4_to_5= ... ruby-3.2.0-preview1 :4_to_5=
Looking at the commit log, I can see that there is a commit that adds special casing for a trailing
= but I don't understand the reason behind why the change was made: https://github.com/ruby/ruby/commit/986a893d7a420b8472c06b2e36b71b8bf00e9e21
@nobu (Nobuyoshi Nakada) I understand that Ruby does not guarantee that
inspect methods are for
eval but Ruby seems to consistently quote invalid
inspect, except for when they end with
=. I think this is not consistent and Ruby might as well not quote
inspect at all, in this case. I think something has to change to keep consistency.