Symbol#inspect bug?


#1

Hallo,

Symbol#inspect should return a valid symbol literal, right?

But it doesn’t for symbols starting with a digit:

irb(main):001:0> p :“9”
:9
=> nil
irb(main):002:0> :9
SyntaxError: compile error
(irb):2: syntax error
from (irb):2

Dominik


#2

On 11/18/05, Dominik B. removed_email_address@domain.invalid wrote:

SyntaxError: compile error
(irb):2: syntax error
from (irb):2

Dominik

It also doesn’t work for many of the operators:

p(:’=’)
:=

p(:=)
SyntaxError: compile error
(irb):14: syntax error
p(:=)

It seems like if the symbol string is not a valid identifier, it
should be quoted by Symbol#inspect.


#3

On Nov 18, 2005, at 3:22 PM, Dominik B. wrote:

Symbol#inspect should return a valid symbol literal, right?

Not according to the RDoc:

$ ri Object#inspect
--------------------------------------------------------- Object#inspect
obj.inspect => string

  Returns a string containing a human-readable representation of
  _obj_. If not overridden, uses the +to_s+ method to generate the
  string.

     [ 1, 2, 3..4, 'five' ].inspect   #=> "[1, 2, 3..4, \"five\"]"
     Time.new.inspect                 #=> "Wed Apr 09 08:54:39

CDT 2003"


#4

On Sat, 19 Nov 2005 00:57:28 +0100, Eric H. removed_email_address@domain.invalid
wrote:

  Returns a string containing a human-readable representation of
  _obj_. If not overridden, uses the +to_s+ method to generate the
  string.

     [ 1, 2, 3..4, 'five' ].inspect   #=> "[1, 2, 3..4, \"five\"]"
     Time.new.inspect                 #=> "Wed Apr 09 08:54:39 CDT  

2003"

Yes, but:

$ ri Symbol#inspect
--------------------------------------------------------- Symbol#inspect
sym.inspect => string

  Returns the representation of sym as a symbol literal.

     :fred.inspect   #=> ":fred"

#5

On Nov 18, 2005, at 4:09 PM, Dominik B. wrote:

  Returns a string containing a human-readable representation of
  _obj_. If not overridden, uses the +to_s+ method to generate  

the
string.

Yes, but:

$ ri Symbol#inspect
Returns the representation of sym as a symbol literal.

I consider Object#inspect to set the intent of all the #inspect
methods, but this may be an oversight.


#6

On 11/18/05, Eric H. removed_email_address@domain.invalid wrote:

Not according to the RDoc:
Returns the representation of sym as a symbol literal.

I consider Object#inspect to set the intent of all the #inspect
methods, but this may be an oversight.

For many of the other core classes (and definitely all other immediate
classes), #inspect returns a representation that is eval’able to get
back an equivalent (or the same) object. When possible, I think that
is what #inspect should do. I think it is a bug that Symbol#inspect
almost does it, but not quite (quotes some cases but not others).

I found this problem when doing code generation. For immediate
objects, I embedded the value in the code directly by using #inspect.
I had to put in a hack for Symbol because of the problem discussed.


#7

On 11/18/05, Eric M. removed_email_address@domain.invalid wrote:

For many of the other core classes (and definitely all other immediate
classes), #inspect returns a representation that is eval’able to get
back an equivalent (or the same) object. When possible, I think that
is what #inspect should do. I think it is a bug that Symbol#inspect
almost does it, but not quite (quotes some cases but not others).

I agree this should be fixed. I wrote something that I think shows all
the problem cases (at least for single characters):

32.upto(126) do |i|
c = i.chr
s = “:”#{c}""
if c == “”" or c == “\”
s = “:”\#{c}""
end
symbol = eval(s)
begin
symbol = eval(symbol.inspect)
rescue SyntaxError
puts “Failed to eval inspected form of #{s}”
end
end

The results:

Failed to eval inspected form of :"!"
Failed to eval inspected form of :“0”
Failed to eval inspected form of :“1”
Failed to eval inspected form of :“2”
Failed to eval inspected form of :“3”
Failed to eval inspected form of :“4”
Failed to eval inspected form of :“5”
Failed to eval inspected form of :“6”
Failed to eval inspected form of :“7”
Failed to eval inspected form of :“8”
Failed to eval inspected form of :“9”
Failed to eval inspected form of :"="
Failed to eval inspected form of :"@"

Ryan


#8

Hi,

In message “Re: Symbol#inspect bug?”
on Sat, 19 Nov 2005 08:22:20 +0900, “Dominik B.” removed_email_address@domain.invalid
writes:

|But it doesn’t for symbols starting with a digit:
|
|irb(main):001:0> p :“9”
|:9

Which version are you using?

% ruby -ve ‘p :“9”’
ruby 1.8.4 (2005-10-29) [i486-linux]
:“9”

So it’s reserved to be fixed.

						matz.

#9

Eric M. removed_email_address@domain.invalid wrote:

almost does it, but not quite (quotes some cases but not others).
Although I’d agree that Symbol#inspect can be improved and should be
changend (as it’s an easy fix) I have a different opinion about the
usage of
inspect in general: even inspect methods of core classes fail to return
something that is proper ruby code.

$ ruby -e ‘p Object.new’
#Object:0x100f6b28
$ ruby -e ‘a=[1];a<<a;p a’
[1, […]]

I found this problem when doing code generation. For immediate
objects, I embedded the value in the code directly by using #inspect.
I had to put in a hack for Symbol because of the problem discussed.

IMHO relying on #inspect for code generation is inappropriate. As the
rdoc
of Object#inspect indicates it’s meant to yield a human readable
representation. If you want to generate code you should use another
mechanism. For example, you can define a separate method (even if it
calls
#inspect as default implementation). Or you use YAML / Marshal for
complex
data structures.

Kind regards

robert

#10

On 11/19/05, Robert K. removed_email_address@domain.invalid wrote:

$ ruby -e ‘p Object.new’
#Object:0x100f6b28
$ ruby -e ‘a=[1];a<<a;p a’
[1, […]]

I didn’t say all core classes return something evalable for #inspect
(I said many). Here’s the list I see:

FalseClass, TrueClass, NilClass
Fixnum, Bignum
Float
String
Regexp
Symbol - close but no cigar
Class - kind of - it returns a constant for class that can be evaled
Array, Hash, Range - if no recursion and all elements have an evalable
#inspect

I found this problem when doing code generation. For immediate
objects, I embedded the value in the code directly by using #inspect.
I had to put in a hack for Symbol because of the problem discussed.

IMHO relying on #inspect for code generation is inappropriate. As the rdoc
of Object#inspect indicates it’s meant to yield a human readable
representation. If you want to generate code you should use another
mechanism. For example, you can define a separate method (even if it calls
#inspect as default implementation). Or you use YAML / Marshal for complex
data structures.

Notice I said only immediate objects. This was actually only an
optimization. For non-immediate objects, I’m putting them in an
instance variable to be accessed by the generated code. For immediate
objects there was no reason for this as they were immutable and had no
object creation overhead. Depending on the instance variable usage
overhead vs. object creation overhead, I might do the same for Float
and other immutable, evalable #inspect classes. Again, this is only
an optimization - handling some classes differently doesn’t change the
functionality.


#11

On 11/19/05, Yukihiro M. removed_email_address@domain.invalid wrote:

Which version are you using?

% ruby -ve ‘p :“9”’
ruby 1.8.4 (2005-10-29) [i486-linux]
:“9”

So it’s reserved to be fixed.

                                                    matz.

Thanks matz. I just downloaded 1.8.4 preview1 and tried this out. It
looks like only one case isn’t fixed yet (:"["):

[eric@localhost ruby-1.8.4]$ ./ruby -v
ruby 1.8.4 (2005-10-29) [i686-linux]

[eric@localhost ruby-1.8.4]$ ./ruby
1.upto(255) do |c0|
0.upto(255) do |c1|
str = c0.chr
str.concat(c1.chr) if c1.nonzero?
inspect0 = “:#{str.inspect}”
eval0 = eval(inspect0)
inspect1 = eval0.inspect
begin
eval1 = eval(inspect1)
eval1==eval0 or puts “#{eval1}!=#{eval0}”
rescue SyntaxError
puts “Couldn’t eval(#{inspect1} =
eval(#{inspect0}).inspect)”
end
end
end

Couldn’t eval(:[ = eval(:"[").inspect)

I didn’t realize that symbols can’t handle empty strings or the null
character until I tried this.


#12

On 11/19/05, Eric M. removed_email_address@domain.invalid wrote:

something that is proper ruby code.
Fixnum, Bignum
Float
String
Regexp
Symbol - close but no cigar
Class - kind of - it returns a constant for class that can be evaled
Array, Hash, Range - if no recursion and all elements have an evalable #inspect

Float: NaN, Infinity, -Infinity
Class: Class.new #==> #Class:0x760fe0
Regexp:
insert = ‘#{23}’
==>"#{23}"
re = /#{insert}/
==>/#{23}/
eval(re.inspect)
==>/23/
… where /#{23}/ is a valid regexp which matches 23 hash characters.

Still, I like that for most cases in core classes, #inspect yields an
eval-able value. This makes it a lot nicer for learning Ruby in IRB.

cheers,
Mark


#13

On 11/19/05, Mark H. removed_email_address@domain.invalid wrote:

Float: NaN, Infinity, -Infinity

It’s annoying that these aren’t constants.

Class: Class.new #==> #Class:0x760fe0

Yeah, I knew Class#inspect was full of holes for it being evalable.

Regexp:
insert = ‘#{23}’
==>"#{23}"
re = /#{insert}/
==>/#{23}/
eval(re.inspect)
==>/23/
… where /#{23}/ is a valid regexp which matches 23 hash characters.

I think this is a bug. These should be equivalent:

irb(main):001:0> /#{23}/
=> /#{23}/
irb(main):002:0> /#{’#{23}’}/
=> /#{23}/

Regexp#inspect should always escape ‘#’.


#14

Eric M. wrote:

Regexp#inspect should always escape ‘#’.

#inspect is for human-readable strings. If they happen
to be evalable, it’s a side effect.

Hal


#15

Hi,

At Sat, 19 Nov 2005 23:40:16 +0900,
Eric M. wrote in [ruby-talk:166520]:

Thanks matz. I just downloaded 1.8.4 preview1 and tried this out. It
looks like only one case isn’t fixed yet (:"["):

Thank you, fixed it now.


#16

Eric M. wrote:

I didn’t realize that symbols can’t handle empty strings or the null
character until I tried this.

Well, at least in 1.8.2 they can handle empty strings, but it is
somewhat tricky:

irb(main):001:0> :"#{}"
ArgumentError: interning empty string
from (irb):1
irb(main):002:0> :"#{""}"
=> :

Symbol#inspect doesn’t quite work there, though. :slight_smile:

Also, there was more cases like :"$10" that don’t work in 1.8.2 and I’m
not sure if they have already been fixed for 1.9. I think I listed most
of them in [ruby-core:03573].