Strange behavior of unary +@ for Fixnum?

A

Alexandre Mutel

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

Colin Bartlett

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 (-7**2)
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( :+@ ) ?
 
C

Caleb Clausen

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
(-7**2)
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...
 
C

Colin Bartlett

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 (-7**2) I was assuming (without trying) that (+7**2)
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
=A0+ 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:

=A0++++++++++++++++++++++++++7 =A0#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=3D1.9.1 release-date=3D2009-07-16 platform=3Di386-mingw32
class Fixnum
def +@() ; puts "in +@" ; self ; end
def -@() ; puts "in -@" ; self * -1 ; end
end
-7 #=3D> -7
+7 #=3D> 7
-(7) #=3D> in -@ #=3D> -7
+(7) #=3D> in +@ #=3D> 7
-7**2 #=3D> in -@ #=3D> -49
+7**2 #=3D> 49 # note difference between this and -7**2
---7 #=3D> in -@ #=3D> in -@ #=3D> -7
- 7 #=3D> in -@ #=3D> -7
+++7 #=3D> in +@ #=3D> in +@ #=3D> 7
+ 7 #=3D> in +@ #=3D> 7

# ruby=3D1.8.6 release-date=3D2007-09-24 platform=3Di386-mswin32
# the only differences are, as you said:
+++7 #=3D> 7
+ 7 #=3D> 7
 
A

Alexandre Mutel

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! ;)
 
M

Marc Heiler

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

Tony Arcieri

[Note: parts of this message were removed to make it a legal post.]

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:
=> -7

So much for the "it's just the lexer!" theory...
 
T

Tony Arcieri

[Note: parts of this message were removed to make it a legal post.]

So much for the "it's just the lexer!" theory...

Err whoops, perhaps I've had a little too much wine...
YES 7
=> nil
 
R

Ryan Davis

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
 
A

Alexandre Mutel

Marc said:
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...
 
R

Ryan Davis

=20
I mean, when you need to use intensively operators, there are lots of=20=
(small) issues, difference between 1.8.x and 1.9.x, difference with=20
JRuby with --1.9 switch... Actually, I'm using operators overloading = for=20
a DSL to accept new If/Else/Elsif expressions, and have to deal with=20=
those issues.
For example the unary +@ operator on symbols is not really working in=20=

How is it not working on symbols?

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

def -@
puts "NO #{self}"
end
end

-:x # =3D> NO x
+:x # =3D> :x
+:)x) # =3D> YES x
-:)x) # =3D> NO x
+:)x) # =3D> YES x
:x.send:)-@) # =3D> NO x
:x.send:)+@) # =3D> YES x
As well as the ! operator that was finally introduced in 1.9.x.=20

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=20
that +@ operator for numeric are in fact consumed by the parser as=20
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...
 
C

Caleb Clausen

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

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 +@?
 
T

Tony Arcieri

[Note: parts of this message were removed to make it a legal post.]

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

class Fixnum
def +@
puts "YES"
end

def -@
puts "NO"
end
end

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

Kraftwerk?
 
A

Alexandre Mutel

Ryan said:
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! ;) 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...
 

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,780
Messages
2,569,611
Members
45,273
Latest member
DamonShoem

Latest Threads

Top