Bug(?) when using symbols for variables/methods

Hi, all

Is this a bug, a feature, or just something weird?

irb(main):001:0> class Foo; def initialize(bar); @23 = bar; end; end
SyntaxError: compile error
(irb):1: @2' is not allowed as an instance variable name from (irb):1 irb(main):002:0> class Foo; end => nil irb(main):003:0> f=Foo.new => #<Foo:0x46aa8> irb(main):004:0> f.instance_variable_set(:@23, 23) SyntaxError: compile error (irb):4:@2’ is not allowed as an instance variable name
from (irb):4
irb(main):005:0> f.instance_variable_set(:"@23", 23)
=> 23
irb(main):006:0> f
=> #<Foo:0x46aa8 @23=23>
irb(main):007:0> RUBY_VERSION
=> “1.9.0”

@23 is an illegal instance variable. (yup)

  • In line 1, I tried setting it in #initialize. didn’t work, as
    expected.
  • line 4, tried setting using a normal symbol. again, didn’t work.
  • line 5, tried setting it using a quoted symbol. Somehow, it works…

I realize that this is contrived. But it is a little odd, isn’t it?
If you do the same trick with attr_reader/attr_writer, you can create
accessor functions for the variable. “23” and “23=” show up in the
methods() array. You can call them, but only using foo.send(:“23=”,
42).

–Mark

Hi,

At Wed, 3 Mar 2004 05:20:48 +0900,
Mark Hubbart wrote in [ruby-talk:94087]:

I realize that this is contrived. But it is a little odd, isn’t it?
If you do the same trick with attr_reader/attr_writer, you can create
accessor functions for the variable. “23” and “23=” show up in the
methods() array. You can call them, but only using foo.send(:“23=”,
42).

Indeed.

  • parse.y (rb_intern): instance/class variables should not start with
    a digit. [ruby-talk:94087]

    Index: parse.y
···

===================================================================
RCS file: /cvs/ruby/src/ruby/parse.y,v
retrieving revision 1.316
diff -u -2 -p -r1.316 parse.y
— parse.y 12 Feb 2004 06:23:24 -0000 1.316
+++ parse.y 3 Mar 2004 00:02:29 -0000
@@ -2457,4 +2457,5 @@ none : /* none */ {$$ = 0;}

define SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128)

#endif
+#define is_identfirst(c) (SIGN_EXTEND_CHAR(c)!=-1&&(ISALPHA(c) || (c) == ‘’ || ismbchar(c)))
#define is_identchar(c) (SIGN_EXTEND_CHAR(c)!=-1&&(ISALNUM(c) || (c) == '
’ || ismbchar(c)))

@@ -3154,5 +3155,5 @@ heredoc_identifier()

   default:
  • if (!is_identchar(c)) {
  • if (!is_identfirst(c)) {
    pushback(c);
    if (func & STR_FUNC_INDENT) {
    @@ -4269,5 +4270,5 @@ yylex()

    default:

  •   if (!is_identchar(c)) {
    
  •   if (!is_identfirst(c)) {
      pushback(c);
      return '$';
    

@@ -4294,5 +4295,5 @@ yylex()
}
}

  • if (!is_identchar(c)) {
  • if (!is_identfirst(c)) {
    pushback(c);
    return ‘@’;
    @@ -4331,5 +4332,5 @@ yylex()
    c = nextc();
    } while (is_identchar(c));
  • if ((c == ‘!’ || c == ‘?’) && is_identchar(tok()[0]) && !peek(‘=’)) {
  • if ((c == ‘!’ || c == ‘?’) && is_identfirst(tok()[0]) && !peek(‘=’)) {
    tokadd(c);
    }
    @@ -5861,5 +5862,5 @@ rb_intern(name)
    break;
    default:
  • if (name[0] != ‘_’ && !ISALPHA(name[0]) && !ismbchar(name[0])) {
  • if (!is_identfirst(name[0])) {
    /* operators */
    int i;
    @@ -5895,6 +5856,8 @@ rb_intern(name)
    break;
    }
  • while (m <= name + last && is_identchar(*m)) {
  • m += mbclen(*m);
  • if (m <= name + last && is_identfirst(*m)) {
  • do {
  •   m += mbclen(*m);
    
  • } while (m <= name + last && is_identchar(*m));
    }
    if (*m) id = ID_JUNK;


Nobu Nakada

Hi,

At Wed, 3 Mar 2004 09:15:28 +0900,
nobu.nokada@softhome.net wrote in [ruby-talk:94099]:

@@ -5861,5 +5862,5 @@ rb_intern(name)
break;
default:

  • if (name[0] != ‘_’ && !ISALPHA(name[0]) && !ismbchar(name[0])) {
  • if (!is_identfirst(name[0])) {
    /* operators */
    int i;
    @@ -5895,6 +5856,8 @@ rb_intern(name)
    break;
    }
  • while (m <= name + last && is_identchar(*m)) {
  • m += mbclen(*m);
  • if (m <= name + last && is_identfirst(*m)) {
  • do {
  • m += mbclen(*m);
    
  • } while (m <= name + last && is_identchar(*m));
    }
    if (*m) id = ID_JUNK;

Sorry, wrong patch.

@@ -5859,7 +5860,8 @@ rb_intern(name)
}
m++;

  • if (!is_identfirst(*m)) id = ID_JUNK;
    break;
    default:
  • if (name[0] != ‘_’ && !ISALPHA(name[0]) && !ismbchar(name[0])) {
  • if (!is_identfirst(name[0])) {
    /* operators */
    int i;
···


Nobu Nakada