Symbol#inspect bug?

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

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.

···

On 11/18/05, Dominik Bathon <dbatml@gmx.de> wrote:

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

Not according to the RDoc:

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

···

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

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

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

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

Hi,

···

In message "Re: Symbol#inspect bug?" on Sat, 19 Nov 2005 08:22:20 +0900, "Dominik Bathon" <dbatml@gmx.de> 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.

Yes, but:

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

···

On Sat, 19 Nov 2005 00:57:28 +0100, Eric Hodel <drbrain@segment7.net> wrote:

On Nov 18, 2005, at 3:22 PM, Dominik Bathon 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"

------------------------------------------------------------------------
      Returns the representation of sym as a symbol literal.

         :fred.inspect #=> ":fred"

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.

···

On 11/19/05, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

Hi,

In message "Re: Symbol#inspect bug?" > on Sat, 19 Nov 2005 08:22:20 +0900, "Dominik Bathon" <dbatml@gmx.de> 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.

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

···

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

On Sat, 19 Nov 2005 00:57:28 +0100, Eric Hodel > <drbrain@segment7.net> wrote:

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

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

Not according to the RDoc:

$ ri Object#inspect
      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.

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

Eric Mahurin 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].

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.

···

--
Nobu Nakada

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.

···

On 11/18/05, Eric Hodel <drbrain@segment7.net> wrote:

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

> On Sat, 19 Nov 2005 00:57:28 +0100, Eric Hodel > > <drbrain@segment7.net> wrote:
>
>> On Nov 18, 2005, at 3:22 PM, Dominik Bathon wrote:
>>
>>> Symbol#inspect should return a valid symbol literal, right?
>>
>> Not according to the RDoc:
>>
>> $ ri Object#inspect
>> 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.

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

···

On 11/18/05, Eric Mahurin <eric.mahurin@gmail.com> 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).

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

Not according to the RDoc:

$ ri Object#inspect
      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.

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

···

Eric Mahurin <eric.mahurin@gmail.com> wrote:

On 11/18/05, Eric Hodel <drbrain@segment7.net> wrote:

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

On Sat, 19 Nov 2005 00:57:28 +0100, Eric Hodel >>> <drbrain@segment7.net> wrote:

On Nov 18, 2005, at 3:22 PM, Dominik Bathon 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).

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

···

On 11/19/05, Robert Klemme <bob.news@gmx.net> 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).
>
> 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 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

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

···

On 11/19/05, Eric Mahurin <eric.mahurin@gmail.com> wrote:

On 11/19/05, Robert Klemme <bob.news@gmx.net> wrote:

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

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 '#'.

···

On 11/19/05, Mark Hubbart <discordantus@gmail.com> wrote:

Eric Mahurin wrote:

···

On 11/19/05, Mark Hubbart <discordantus@gmail.com> wrote:

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