Strange behavior of unary +@ for Fixnum?

It seems that it’s not possible to use the unary +@ operator for Fixnum
in a “short form” way :

class Fixnum
def +@
puts “YES #{self}”
end
end
=> nil

+50
=> 50 # Unexpected result : should print YES 50

+(50)
YES 50
=> nil

Although, the +(fixnum) form is working… i wish i could use the
shorter form!

I suspect Ruby’s parser to perform some unexpected “optimization”
here…

On Mon, Dec 21, 2009 at 10:51 PM, Alexandre M.
[email protected] wrote:

I suspect Ruby’s parser to perform some unexpected “optimization”
here…

I haven’t looked at the source code, but I think I’m right in saying
that
Ruby parses (-7) as an integer literal, unless it’s an expression like
(-72)
in which case it’s parsed as (-(7
2)), that is (7**2).send( :-@ )
By analogy, it seems that the parser is treating (+7) as an integer
literal,
not as 7.send( :+@ ) ?

On 12/21/09, Colin B. [email protected] wrote:

I haven’t looked at the source code, but I think I’m right in saying that
Ruby parses (-7) as an integer literal, unless it’s an expression like
(-72)
in which case it’s parsed as (-(7
2)), that is (7**2).send( :-@ )
By analogy, it seems that the parser is treating (+7) as an integer literal,
not as 7.send( :+@ ) ?

This is correct. + or - at the start of an numeric literal is
tokenized as part of that literal. (Except in the ** case, as you
say.)

The situation is somewhat better in 1.9, where at least

  • 7 #with a space in between
    is treated as +@ method applied to the literal 7. But that doesn’t
    help in 1.8. Note that in ruby 1.8, any number of leading + signs are
    glommed into the integer literal:

++++++++++++++++++++++++++7 #still no method call in 1.8

Having integer literals eat up the leading + or - as part of the
number token is a common ‘optimization’ in many languages…

On Tue, Dec 22, 2009 at 3:45 AM, Caleb C. [email protected]
wrote:

On 12/21/09, Colin B. [email protected] wrote:

Ruby parses (-7) as an integer literal,
unless it’s an expression like (-72)
in which case it’s parsed as (-(7
2)), that is (7**2).send( :-@ )
By analogy, it seems that the parser is treating (+7) as an integer literal,
not as 7.send( :+@ ) ?

This is correct. + or - at the start of an numeric literal is
tokenized as part of that literal. (Except in the ** case, as you say.)

I think that your post is more correct than mine: when I put that bit
about (-72) I was assuming (without trying) that (+72)
would behave similarly. Not so, and your comment below
about “+” being eaten up is correct.

The situation is somewhat better in 1.9, where at least

  • 7 #with a space in between
    is treated as +@ method applied to the literal 7. But that doesn’t
    help in 1.8. Note that in ruby 1.8, any number of leading + signs are
    glommed into the integer literal:

++++++++++++++++++++++++++7 #still no method call in 1.8

Having integer literals eat up the leading + or - as part of the
number token is a common ‘optimization’ in many languages…

When all else fails, actually try some code.
Which is what I should have done before my first post.
As confirmation of what you say in your post:

ruby=1.9.1 release-date=2009-07-16 platform=i386-mingw32

class Fixnum
def +@() ; puts “in +@” ; self ; end
def -@() ; puts “in -@” ; self * -1 ; end
end
-7 #=> -7
+7 #=> 7
-(7) #=> in -@ #=> -7
+(7) #=> in +@ #=> 7
-72 #=> in -@ #=> -49
+7
2 #=> 49 # note difference between this and -7**2
—7 #=> in -@ #=> in -@ #=> -7

  • 7 #=> in -@ #=> -7
    +++7 #=> in +@ #=> in +@ #=> 7
  • 7 #=> in +@ #=> 7

ruby=1.8.6 release-date=2007-09-24 platform=i386-mswin32

the only differences are, as you said:

+++7 #=> 7

  • 7 #=> 7

“ruby’s operator overloading”

I think it is a quite short topic actually.

Which operators are commonly overloaded in ruby?

I think << and + and perhaps -

Marc H. wrote:

I think it is a quite short topic actually.

Which operators are commonly overloaded in ruby?

I mean, when you need to use intensively operators, there are lots of
(small) issues, difference between 1.8.x and 1.9.x, difference with
JRuby with --1.9 switch… Actually, I’m using operators overloading for
a DSL to accept new If/Else/Elsif expressions, and have to deal with
those issues.

For example the unary +@ operator on symbols is not really working in
1.8.x. As well as the ! operator that was finally introduced in 1.9.x.
For the Fixnum, i didn’t find any documentation (until here) that states
that +@ operator for numeric are in fact consumed by the parser as
literals…

On Dec 23, 2009, at 01:37 , Alexandre M. wrote:

Marc H. wrote:

I think it is a quite short topic actually.

Which operators are commonly overloaded in ruby?

I mean, when you need to use intensively operators, there are lots of
(small) issues, difference between 1.8.x and 1.9.x, difference with
JRuby with --1.9 switch… Actually, I’m using operators overloading for
a DSL to accept new If/Else/Elsif expressions, and have to deal with
those issues.

For example the unary +@ operator on symbols is not really working in
1.8.x.

How is it not working on symbols?

class Symbol
def +@
puts “YES #{self}”
end

def -@
puts “NO #{self}”
end
end

-:x # => NO x
+:x # => :x
+(:x) # => YES x
-(:x) # => NO x
+(:x) # => YES x
:x.send(:-@) # => NO x
:x.send(:+@) # => YES x

As well as the ! operator that was finally introduced in 1.9.x.

Have you filed any bugs (or even sent email) against ruby-core for the !
operator?

For the Fixnum, i didn’t find any documentation (until here) that states
that +@ operator for numeric are in fact consumed by the parser as
literals…

Did you actually look at a grammar for ruby? There has been one online
for just about forever (granted it is from 1.4, but I don’t think it has
changed all that much in this arena). You can also look at ParseTree’s
output, or ruby_parser’s, or, or, or…

Thanks for your precise answer. The integer literal “shortcut” makes
sense.

Although, being a newbie in the Ruby world, It’s quite difficult to find
a complete and detailed description of ruby’s operator overloading
capabilities (and more particularly on restrictions, difference between
1.8.x and 1.9.x… etc.). It would be worth from one ruby’s expert to
write a nice article about this! :wink:

On 12/23/09, Ryan D. [email protected] wrote:

end

def -@
puts “NO #{self}”
end
end

-:x # => NO x
+:x # => :x

Ummmmm… does that second line really make sense to you? Is there
any reason why the + in +:sym should be ignored in_the_lexer, with
not even a call to +@?

Ryan D. wrote:

How is it not working on symbols?
+:x # => :x

Have you filed any bugs (or even sent email) against ruby-core for the !
operator?

This is exactly the case that was not working! :wink: I didn’t report any
issue to 1.8.x because it was fixed on 1.9.x and i assume that they are
not going to backport all fixed issues from 1.9.x.
Although, I did a report to JRuby for both +@ and ! operators and they
did a quick fix that should be available for 1.5.

Did you actually look at a grammar for ruby? There has been one online
for just about forever (granted it is from 1.4, but I don’t think it has
changed all that much in this arena). You can also look at ParseTree’s
output, or ruby_parser’s, or, or, or…
I agree that there are several ways to get this information (even
looking at Ruby source code parser), but i found that redirecting to the
BNF grammaar of the language for a newcommer is quite a tough way…

On Tue, Dec 22, 2009 at 8:40 PM, Tony A. [email protected] wrote:

So much for the “it’s just the lexer!” theory…

Err whoops, perhaps I’ve had a little too much wine…

7.send :‘+@’
YES 7
=> nil

On Mon, Dec 21, 2009 at 3:51 PM, Alexandre M.
[email protected]wrote:

It seems that it’s not possible to use the unary +@ operator for Fixnum
in a “short form” way :

class Fixnum
def +@
puts “YES #{self}”
end
end
=> nil

Just to further fan the flames of WTF:

class Fixnum
def +@
puts “YES #{self}”
end
end
=> nil
7.send :‘-@’
=> -7

So much for the “it’s just the lexer!” theory…

On Dec 22, 2009, at 19:42 , Tony A. wrote:

On Tue, Dec 22, 2009 at 8:40 PM, Tony A. [email protected] wrote:

So much for the “it’s just the lexer!” theory…

Err whoops, perhaps I’ve had a little too much wine…

class Fixnum
def +@
puts “YES #{self}”
end

def -@
puts “NO #{self}”
end
end

-7 # => -7
+7 # => 7
-(7) # => NO 7
+(7) # => YES 7
7.send(:-@) # => NO 7
7.send(:+@) # => YES 7

On Wed, Dec 23, 2009 at 12:43 AM, Ryan D.
[email protected]wrote:

-7 # => -7
+7 # => 7
-(7) # => NO 7
+(7) # => YES 7
7.send(:-@) # => NO 7
7.send(:+@) # => YES 7

class Fixnum
def +@
puts “YES”
end

def -@
puts “NO”
end
end

%w(+ -).each { |op| 4.times { 42.send “#{op}@” } }

Kraftwerk?