Symbol#inspect bug?

D

Dominik Bathon

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
=3D> nil
irb(main):002:0> :9
SyntaxError: compile error
(irb):2: syntax error
from (irb):2


Dominik
 
E

Eric Mahurin

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
=3D> nil
irb(main):002:0> :9
SyntaxError: compile error
(irb):2: syntax error
from (irb):2


Dominik

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

p:)'=3D')
:=3D

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


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

Eric Hodel

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"
 
D

Dominik Bathon

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

Not according to the RDoc:

$ ri Object#inspect
--------------------------------------------------------- Object#inspec= t
obj.inspect =3D> 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 #=3D> "[1, 2, 3..4, \"five\"]= "
Time.new.inspect #=3D> "Wed Apr 09 08:54:39 CD= T =20
2003"

Yes, but:

$ ri Symbol#inspect
--------------------------------------------------------- Symbol#inspect
sym.inspect =3D> string
 
E

Eric Hodel

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.
 
E

Eric Mahurin

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.=20
I had to put in a hack for Symbol because of the problem discussed.
 
R

Ryan Leavengood

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 =3D i.chr
s =3D ":\"#{c}\""
if c =3D=3D "\"" or c =3D=3D "\\"
s =3D ":\"\\#{c}\""
end
symbol =3D eval(s)
begin
symbol =3D 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 :"=3D"
Failed to eval inspected form of :"@"

Ryan
 
R

Robert Klemme

Eric Mahurin said:
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).

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
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: Symbol#inspect bug?"

|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.
 
E

Eric Mahurin

Hi,

In message "Re: Symbol#inspect bug?"
|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.

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 =3D c0.chr
str.concat(c1.chr) if c1.nonzero?
inspect0 =3D ":#{str.inspect}"
eval0 =3D eval(inspect0)
inspect1 =3D eval0.inspect
begin
eval1 =3D eval(inspect1)
eval1=3D=3Deval0 or puts "#{eval1}!=3D#{eval0}"
rescue SyntaxError
puts "Couldn't eval(#{inspect1} =3D eval(#{inspect0}).inspect)"
end
end
end

Couldn't eval:)[ =3D eval:)"[").inspect)


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

Eric Mahurin

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).

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=3D[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 #ins=
pect
IMHO relying on #inspect for code generation is inappropriate. As the rd= oc
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 cal= ls
#inspect as default implementation). Or you use YAML / Marshal for compl= ex
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.
 
F

Florian Groß

Eric said:
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. :)

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].
 
E

Eric Mahurin

Float: NaN, Infinity, -Infinity

It's annoying that these aren't constants.
Class: Class.new #=3D=3D> #<Class:0x760fe0>

Yeah, I knew Class#inspect was full of holes for it being evalable.
Regexp:
insert =3D '#{23}'
=3D=3D>"\#{23}"
re =3D /#{insert}/
=3D=3D>/#{23}/
eval(re.inspect)
=3D=3D>/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}/
=3D> /\#{23}/
irb(main):002:0> /#{'#{23}'}/
=3D> /#{23}/

Regexp#inspect should always escape '#'.
 
H

Hal Fulton

Eric said:
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 '#'.

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

Hal
 
N

nobu.nokada

Hi,

At Sat, 19 Nov 2005 23:40:16 +0900,
Eric Mahurin 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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top