Ruby doesn't implement x++ for Fixnum's because?

Hi,

In The Well Grounded Rubyist (which, along with The Ruby Way, I
love), Dave Black presents a justification for the x++ omission in
Ruby. I thought I'd see whether I could implement just the
incrementing portion of C's x++ functionality (without the prefix/
postfix issues) in pure Ruby. I wasn’t willing to delve into Matz’
implementation of higher-level Ruby functions or low-level C/C++
code. Below is what I came up with.

Q1. Test 1 failed, I imagine, because the interpret thought “Ah, 7’s
a Fixnum which I ‘ve seen billions of times, so I know what to do with
it.” Thus, it ignored my over-riding definition of Fixnum. So I
call it “compiler error”, to use the vernacular, by reporting that x
had no method “pp”. Am I all wet?

Test 2 passed, but it with a couple of anomalies:

Q2. x.to_s yielded x’s class and address, suggesting x had become a
“semi-Fixed Num”, i.e, x now stored a REFERENCE to the to x’s data,
rather than the immediate storage of the data, as interpreter is wont
to do with Fixnum’s. Am I all wet?

Q3. y.inspect yielded only it’s value (8) and nothing else,
suggesting the x.pp yielded a full-fledged Fixnum. Am I all wet?

Dave Black argues that since Fixnum values use immediate storage
rather than referenced storage, x=1;x++ would be akin to changing 1
into 2. This example somewhat supports that view, but the
interpreter sidestepped the matter by creating a reference for x’s
value and an immediate value for y (=x.pp).

Any ideas,
Richard

class FixNum
  attr :val
  def initialize (fixnum)
    puts "Initializing object %d" % fixnum
    raise "Initializer not a Fixnum" if
  fixnum.class != Fixnum
    puts "\nInitializing Fixnum to %d" % fixnum
    @val = fixnum
  end

  def pp
    @val+=1
  end
end

# Test 1 (Failure)
x = 7; y = x.pp; z =x.class # undefined method `pp' for 7:Fixnum
(NoMethodError)

# Test 2 (Success)
x = FixNum.new(7); y = x.pp; z =x.class
puts [x.to_s, y.inspect, z.to_s].join("; ") # => <FixNum:0x2b62694>;
8; FixNum

Hi --

Hi,

In The Well Grounded Rubyist (which, along with The Ruby Way, I
love),

Thanks :slight_smile:

Dave Black presents a justification for the x++ omission in
Ruby. I thought I'd see whether I could implement just the
incrementing portion of C's x++ functionality (without the prefix/
postfix issues) in pure Ruby. I wasn’t willing to delve into Matz’
implementation of higher-level Ruby functions or low-level C/C++
code. Below is what I came up with.

Q1. Test 1 failed, I imagine, because the interpret thought “Ah, 7’s
a Fixnum which I ‘ve seen billions of times, so I know what to do with
it.” Thus, it ignored my over-riding definition of Fixnum. So I
call it “compiler error”, to use the vernacular, by reporting that x
had no method “pp”. Am I all wet?

x is a FixNum, not a Fixnum. In fact you're not actually reopening
Fixnum; you've created an entirely new, unrelated class called FixNum.

Is that what you meant to do? (I'll hold off discussing your other
questions further pending clarification of that :slight_smile:

David

···

On Fri, 30 Oct 2009, RichardOnRails wrote:

--
The Ruby training with D. Black, G. Brown, J.McAnally
Compleat Jan 22-23, 2010, Tampa, FL
Rubyist http://www.thecompleatrubyist.com

David A. Black/Ruby Power and Light, LLC (http://www.rubypal.com)

Hi,

Please ignore my questions. I just discovered a major mistake: I
thought I was overriding Ruby's Fixnum class, but I misspelled it at
FixNum. That error invalidates most if not all of the things I
reported. Mea Culpa.

I'll correct my errors and probably have a new theory subsequently.

Best wishes,
Richard

···

On Oct 29, 9:18 pm, RichardOnRails <RichardDummyMailbox58...@USComputerGurus.com> wrote:

Hi,

In The Well Grounded Rubyist (which, along with The Ruby Way, I
love), Dave Black presents a justification for the x++ omission in
Ruby. I thought I'd see whether I could implement just the
incrementing portion of C's x++ functionality (without the prefix/
postfix issues) in pure Ruby. I wasn’t willing to delve into Matz’
implementation of higher-level Ruby functions or low-level C/C++
code. Below is what I came up with.

Q1. Test 1 failed, I imagine, because the interpret thought “Ah, 7’s
a Fixnum which I ‘ve seen billions of times, so I know what to do with
it.” Thus, it ignored my over-riding definition of Fixnum. So I
call it “compiler error”, to use the vernacular, by reporting that x
had no method “pp”. Am I all wet?

Test 2 passed, but it with a couple of anomalies:

Q2. x.to_s yielded x’s class and address, suggesting x had become a
“semi-Fixed Num”, i.e, x now stored a REFERENCE to the to x’s data,
rather than the immediate storage of the data, as interpreter is wont
to do with Fixnum’s. Am I all wet?

Q3. y.inspect yielded only it’s value (8) and nothing else,
suggesting the x.pp yielded a full-fledged Fixnum. Am I all wet?

Dave Black argues that since Fixnum values use immediate storage
rather than referenced storage, x=1;x++ would be akin to changing 1
into 2. This example somewhat supports that view, but the
interpreter sidestepped the matter by creating a reference for x’s
value and an immediate value for y (=x.pp).

Any ideas,
Richard

class FixNum
attr :val
def initialize (fixnum)
puts "Initializing object %d" % fixnum
raise "Initializer not a Fixnum" if
fixnum.class != Fixnum
puts "\nInitializing Fixnum to %d" % fixnum
@val = fixnum
end

def pp
@val+=1
end
end

# Test 1 (Failure)
x = 7; y = x.pp; z =x.class # undefined method `pp' for 7:Fixnum
(NoMethodError)

# Test 2 (Success)
x = FixNum.new(7); y = x.pp; z =x.class
puts [x.to_s, y.inspect, z.to_s].join("; ") # => <FixNum:0x2b62694>;
8; FixNum

IMHO the story goes like this: absence of postfix ++ and -- is a
consequence of the fact that numeric types are immutable in Ruby which
makes an assignment necessary for these operators. Although that
would be doable, it would not immediately be obvious when looking at
"foo++". On the other side, "foo += 1" makes the assignment obvious
while still being pretty concise (you do not have to write "foo = foo
+ 1").

Which brings us to the question: what is the advantage of immutable
numbers? First, it avoids errors that could be caused by aliasing
(two objects refer the same object, one of them changes it, it changes
for the other one as well without being expected). Then, it is quite
natural if you consider mathematical numbers: they cannot change.

Additionally, the expression "1" can always refer to the same object
(in reality it's a bit different but from a Ruby programmer's
perspective the difference is not noticeable) which in fact makes
using numeric constants very efficient (as opposed to the expression
"'foo'" which constructs a new String instance on every invocation,
albeit with a shared char array underneath which eases the pain a
bit).

This in turn makes integer math pretty efficient because if numbers
were mutable Ruby would have to create a new object for every result
of an operator evaluation. I am not saying that Ruby is ideal for
number crunching but it could be significantly slower if certain
design decisions would have been made differently.

Kind regards

robert

···

2009/10/30 RichardOnRails <RichardDummyMailbox58407@uscomputergurus.com>:

I'll correct my errors and probably have a new theory subsequently.

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

IMHO the story goes like this: absence of postfix ++ and -- is a
consequence of the fact that numeric types are immutable in Ruby which
makes an assignment necessary for these operators.

You could "decorate" it with such a method though. This could look
something like this:

    class FixNum < BasicObject

        def initialize(fn)
            @fn = fn
        end

        def succ!
            @fn += 1
        end

        def method_missing(*args, &block)
            @fn.send(*args, &block)
        end

    end

    a = FixNum.new(1)
    a.succ!
    p a
    => 2

Whether this is good practice or marginally useful ...

I think that theres a more fundamental problem with ++ in a language
like ruby, which has to do with the difference between objects and
variables.

The c ++ and -- operators change a variable, NOT a value.

so in C

  a = 1
  b = a
  a++

a is now 2, but b is still 1.

Now, consider not immutable objects, but defining ++ for a mutable
object. I've named the method plus_plus instead of ++ since I can do
the former, but not the latter.

class String
  def plus_plus
    self << " plus a plus"
  end
end

a = "A non-plussed string"
b = a

puts "a is #{a.inspect}"
puts "b is #{b.inspect}"

a.plus_plus

puts "a is #{a.inspect}"
puts "b is #{b.inspect}"

When we run this we see that the result is:

a is "A non-plussed string"
b is "A non-plussed string"
a is "A non-plussed string plus a plus"
b is "A non-plussed string plus a plus"

Because in languages like Ruby with object reference variable
semantics, methods can only operate on objects, not the variables
which reference them.

So if you COULD successfully define Fixnum#++, or Fixnum#plus_plus:

a = 1
a++

could only change the singleton instance of 1 into 2, which probably
isn't something you'd really want to do.

By 'you' I'm not aiming at you Robert.

This reminds me of a very hard bug I encountered years ago when I was
first was learning to program in Fortran. In the original Fortran you
could assign a new value to a subroutine parameter inside the
subroutine. If the actual parameter value was an integer literal, you
could literally change 1 to 2, and that's why I know you probably
don't want to do this.

···

On Fri, Oct 30, 2009 at 11:05 AM, Robert Klemme <shortcutter@googlemail.com> wrote:

2009/10/30 RichardOnRails <RichardDummyMailbox58407@uscomputergurus.com>:

I'll correct my errors and probably have a new theory subsequently.

IMHO the story goes like this: absence of postfix ++ and -- is a
consequence of the fact that numeric types are immutable in Ruby which
makes an assignment necessary for these operators. Although that
would be doable, it would not immediately be obvious when looking at
"foo++". On the other side, "foo += 1" makes the assignment obvious
while still being pretty concise (you do not have to write "foo = foo
+ 1").

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Hi Robert,

Thank you for your thoughtful and extensive responses. I apologized
earlier for my sloppy analysis. I hope the following offers higher
quality.

(a) You say, in part:
“... immutable numbers? First, it avoids errors that could be caused
by aliasing (two objects refer the same object, one of them changes
it, it changes for the other one as well without being expected”
(b) Dave Black, in his truly excellent “The Well-Grounded Rubyist”
says, in part:
“Any object that’s represented as an immediate value is always exactly
the same object” and
“The reason [there’s no x=1; x++] is that , due to the immediate
presence of 1 in x, means you’d be changing 1 into 2,
and that makes no sense”

1. I’d rather discuss this matter in concrete terms rather than
abstractions. Please look at the following method (to generate
results) and two statements:

def show(v)
  "Got #{v}, class = #{v.class}, object_id = #{v.object_id}
(v.object_id-1)/2 = #{(v.object_id-1)/2 }"
end

a = 1; show (a) => Got 1; class = Fixnum; object_id = 3; v >> 1
= 1
b = 1; show (b) => Got 1; class = Fixnum; object_id = 3; v >> 1
= 1
a == b => true

Both “a” and “b” have their respective values held as immediate values
(embedded in their object_id’s), but they are NOT the same thing
because they’re ultimately held in their respective entries in the
symbol table. So, object_id’s for Fixnum’s are synthetic. To think
that those object_id’s point to a location in a memory area that
stores the 32-bit 000...001 (in a 32-bit machine/OS) is to contradict
the meaning of immediacy and defeat the very efficiency that immediate
values offer.

2. Now please consider the following supplement to the statements
above:

a += 1; show (a) => Got 2; class = Fixnum; object_id = 5; v >> 1
= 2
show (a) => Got 2; class = Fixnum; object_id = 5; v >> 1 = 2
show (b) => Got 1; class = Fixnum; object_id = 3; v >> 1 = 1

The assignment of “a += 1” to “a” changed a’s object_id to embed a new
value: 2. Despite that change of 1 to 2 in a’s object, “b” remains
set to 1. “b” did not suffer the calamity of a universal change of
all Fixnum 1’s to 2’s.

3. Conclusion:

a += 1 is equivalent to a++’s natural meaning. In fact, we further
supplement the above statements with:

class Fixnum
  def pp # We can’t define ++ because of a compiler restriction.
    self + 1
  end
end

a=1; show(a.pp) => Got 2; class = Fixnum; object_id = 5; v >> 1
= 2
show(b) => Got 1; class = Fixnum; object_id = 3; v >> 1 = 1

Furthermore, pp works fine on the boundary condition for Fixnum’s on a
common 32-bit cpu/OS, i.e. 2**30-1:

a = 2**30-1; show (a) => Got 1073741823; class = Fixnum; object_id
= 2147483647; v >> 1 = 1073741823
a = 2**30; show (a) => Got 1073741824; class = Bignum; object_id =
22737670; v >> 1 = 11368835

So x++ works fine in the form of pp for positive Fixnum’s. I assume
it’ll work fine for non-positives, also.. A compiler change to allow
“def ++” is necessary to finally add ++ to Fixnum.

Again, thanks for your responses to my question.

Best wishes,
Richard

···

On Oct 30, 11:05 am, Robert Klemme <shortcut...@googlemail.com> wrote:

2009/10/30 RichardOnRails <RichardDummyMailbox58...@uscomputergurus.com>:

> I'll correct my errors and probably have a new theory subsequently.

IMHO the story goes like this: absence of postfix ++ and -- is a
consequence of the fact that numeric types are immutable in Ruby which
makes an assignment necessary for these operators. Although that
would be doable, it would not immediately be obvious when looking at
"foo++". On the other side, "foo += 1" makes the assignment obvious
while still being pretty concise (you do not have to write "foo = foo
+ 1").

Which brings us to the question: what is the advantage of immutable
numbers? First, it avoids errors that could be caused by aliasing
(two objects refer the same object, one of them changes it, it changes
for the other one as well without being expected). Then, it is quite
natural if you consider mathematical numbers: they cannot change.

Additionally, the expression "1" can always refer to the same object
(in reality it's a bit different but from a Ruby programmer's
perspective the difference is not noticeable) which in fact makes
using numeric constants very efficient (as opposed to the expression
"'foo'" which constructs a new String instance on every invocation,
albeit with a shared char array underneath which eases the pain a
bit).

This in turn makes integer math pretty efficient because if numbers
were mutable Ruby would have to create a new object for every result
of an operator evaluation. I am not saying that Ruby is ideal for
number crunching but it could be significantly slower if certain
design decisions would have been made differently.

Kind regards

robert

--
remember.guy do |as, often| as.you_can - without endhttp://blog.rubybestpractices.com/

IMHO the story goes like this: absence of postfix ++ and -- is a
consequence of the fact that numeric types are immutable in Ruby which
makes an assignment necessary for these operators.

You could "decorate" it with such a method though. This could look
something like this:

class FixNum < BasicObject

   def initialize\(fn\)
       @fn = fn
   end

   def succ\!
       @fn \+= 1
   end

   def method\_missing\(\*args, &amp;block\)
       @fn\.send\(\*args, &amp;block\)
   end

Hi lith,

can you extol your knowledge on me about what method_missing is doing?
I get what *args and &block is, but not quite sure what's going on?

···

On Fri, Oct 30, 2009 at 1:51 PM, lith <minilith@gmail.com> wrote:

end

a = FixNum.new(1)
a.succ!
p a
=> 2

Whether this is good practice or marginally useful ...

--
Kind Regards,
Rajinder Yadav

http://DevMentor.org

Do Good! - Share Freely, Enrich and Empower people to Transform their lives.

I'll correct my errors and probably have a new theory subsequently.

IMHO the story goes like this: absence of postfix ++ and -- is a
consequence of the fact that numeric types are immutable in Ruby which
makes an assignment necessary for these operators. Although that
would be doable, it would not immediately be obvious when looking at
"foo++". On the other side, "foo += 1" makes the assignment obvious
while still being pretty concise (you do not have to write "foo = foo
+ 1").

I think that theres a more fundamental problem with ++ in a language
like ruby, which has to do with the difference between objects and
variables.

The c ++ and -- operators change a variable, NOT a value.

How their behavior is defined is completely up to the language designer. You could make "a++" syntactic sugar for

(_tmp = a; a = a + 1; _tmp)

in the same way as "a += 1" is syntactic sugar for "a = a + 1" or "a ||= 10" is syntactic sugar for "a || a = 10". In fact the sequence in brackets above would be a completely reasonable way to do it in Ruby: you could use "a++" in a similar way as in C++ and Java without sacrificing Fixnum's immutability.

But: you would hide the assignment in the syntactic sugared version and this could lead to unexpected behavior, like

a = 1
b = a
a++
# now why is b still 1???

For someone unaware of the hidden assignment but aware of the fact that the object referenced by a must be mutable to make this work it would be surprising that b is not changed as well. You could only discover that by looking at #object_id of both (or using #equal?).

so in C

  a = 1
  b = a
  a++

a is now 2, but b is still 1.

Yes - and in C++ you can have it otherwise:

robert@fussel:~$ g++ x.cc && ./a.out
a++=1
a=2
b=2
robert@fussel:~$ cat x.cc

#include <stdio.h>

int main( int argc, const char* argv[] )
{
   int a = 1;
   int &b = a;
   printf("a++=%d\n", a++);
   printf("a=%d\n", a);
   printf("b=%d\n", b);
   return 0;
}

robert@fussel:~$

Now, consider not immutable objects, but defining ++ for a mutable
object. I've named the method plus_plus instead of ++ since I can do
the former, but not the latter.

class String
  def plus_plus
    self << " plus a plus"
  end
end

a = "A non-plussed string"
b = a

puts "a is #{a.inspect}"
puts "b is #{b.inspect}"

a.plus_plus

puts "a is #{a.inspect}"
puts "b is #{b.inspect}"

When we run this we see that the result is:

a is "A non-plussed string"
b is "A non-plussed string"
a is "A non-plussed string plus a plus"
b is "A non-plussed string plus a plus"

Because in languages like Ruby with object reference variable
semantics, methods can only operate on objects, not the variables
which reference them.

So if you COULD successfully define Fixnum#++, or Fixnum#plus_plus:

a = 1
a++

could only change the singleton instance of 1 into 2, which probably
isn't something you'd really want to do.

Not necessarily. If this was implemented in the language the sequence "1" would be an object constructor in the same way as string "constants" are.

robert@fussel:~$ ruby1.8 -e '2.times { puts "foo".object_id }'
-605970738
-605970758

That would the only reasonable way to do it. Then there would be no singleton instance which in turn would have the said performance implications.

I would consider the example from Fortran that you presented (changing the value of the constant 1) rather a bug either in the language implementation or in the design. This does not mean that other languages would have to repeat that. :slight_smile:

Kind regards

  robert

···

On 10/30/2009 08:03 PM, Rick DeNatale wrote:

On Fri, Oct 30, 2009 at 11:05 AM, Robert Klemme > <shortcutter@googlemail.com> wrote:

2009/10/30 RichardOnRails <RichardDummyMailbox58407@uscomputergurus.com>:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

I think that theres a more fundamental problem with ++ in a language
like ruby, which has to do with the difference between objects and
variables.

Personally I see nothing interesting about the behavior of ++ in any mutable
state language.

Now, consider not immutable objects, but defining ++ for a mutable
object. I've named the method plus_plus instead of ++ since I can do
the former, but not the latter.

How is ++ any different from << except for << taking an argument? (given
hypothetical C-like ++ behavior)

There is already extensive precedent in Ruby for destructive method calls
that mutate state, and they all lead to the same confusion.

There is nothing interesting with Ruby in this regard, except that Ruby does
seem to go out of its way to do things immutably by default, which, in my
opinion, is pretty cool. But in the end Ruby is still very much a mutable
state language.

···

On Fri, Oct 30, 2009 at 12:03 PM, Rick DeNatale <rick.denatale@gmail.com>wrote:

--
Tony Arcieri
Medioh/Nagravision

No x++ doesn't work fine if you want it to act like C's post-increment operator.

Let's leave Ruby aside for a moment and consider this snippet of C code.

  int a = 1;
  int b = a++

After these two lines a is 2, and b is 1, since a++ returns the
original value of a and then increments a.

Why this wierd semantic? Because it the original use case was for
pointers rather than integers, and it goes back to C originating
originally as a kind of high level assembly language for the DEC
PDP-11 which had postincrement and predecrement addressing modes used
for stepping through strings or arrays.

Because pre-ANSI C allowed easy spoofing/overlay of types, it also
worked for integers and was used in contexts like for loops
    for(i = 0; i < max;i++)

where the value of the expression i++ was never used, only the side
effect that it left a as 1 higher than before was important.

Because of this, many C/C++ programmers seem to be unaware or forget
that the value of a++ is a, not (a+1). In fact Bjarne Stroustrup used
to rib himself by pointing out that the value of C++ was exactly the
same as C, because he IS certainly aware of the semantics.

Now what happens if we translate my initial snippet into Ruby using
your pp method

class Integer
  # Not need to restrict to FixNums is there
  # Name it pp since ++ isn't a valid Ruby method selector
  def pp
    self + 1
  end
end

a = 1
b = a.pp

puts "a is #{a}, b is #{b}"

Produces not "a is 2, b is 1" as it would if it correctly implemented
C language semantics but

a is 1, b is 2

just the opposite of what would be expected by a C/C++ programmer who
understood the meaning of post-increment ++

The fact of the matter is that you can't write a ++ or a pp method in
Ruby which works like the C post-increment because it requires the
method to change the value of a variable which is bound to the object
and the method only knows what the object knows and the object doesn't
know which variable(s) refer to it.

consider

a = b = c = 1
b.pp

There are at least 3 variables which refer to the Fixnum object 1, The
fact that that reference is through a special form object id computed
by multiplying 1 by 2 and adding 1, as it is in several Ruby
implementations, is irrelevant. So is the fact that Fixnums happen to
be immutable. No object knows what variables reference it, and
wouldn't have a way to directly change those variables bindings
anyway.

The rebinding of a in

a = a.pp

doesn't happen in the pp method it happens in the calling context
because of the assignment expression there.

So if you just want a ++ which returns the incremented value of a
fixnum then you can write it as pp, but you really don't need to since
Integer#succ does just that.

If you want the real semantics of the C/C++ post-increment operator,
I'm afraid you'll have to look for it in a C family language, not an
object reference semantic language like Ruby.

···

On Tue, Nov 3, 2009 at 10:25 PM, RichardOnRails <RichardDummyMailbox58407@uscomputergurus.com> wrote:

a += 1 is equivalent to a++’s natural meaning. In fact, we further
supplement the above statements with:

class Fixnum
def pp # We can’t define ++ because of a compiler restriction.
self + 1
end
end

So x++ works fine in the form of pp for positive Fixnum’s. I assume
it’ll work fine for non-positives, also.. A compiler change to allow
“def ++” is necessary to finally add ++ to Fixnum.

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Hi --

Hi Robert,

Thank you for your thoughtful and extensive responses. I apologized
earlier for my sloppy analysis. I hope the following offers higher
quality.

(a) You say, in part:
“... immutable numbers? First, it avoids errors that could be caused
by aliasing (two objects refer the same object, one of them changes
it, it changes for the other one as well without being expected”
(b) Dave Black, in his truly excellent “The Well-Grounded Rubyist”
says, in part:
“Any object that’s represented as an immediate value is always exactly
the same object” and
“The reason [there’s no x=1; x++] is that , due to the immediate
presence of 1 in x, means you’d be changing 1 into 2,
and that makes no sense”

1. I’d rather discuss this matter in concrete terms rather than
abstractions. Please look at the following method (to generate
results) and two statements:

def show(v)
"Got #{v}, class = #{v.class}, object_id = #{v.object_id}
(v.object_id-1)/2 = #{(v.object_id-1)/2 }"
end

a = 1; show (a) => Got 1; class = Fixnum; object_id = 3; v >> 1
= 1
b = 1; show (b) => Got 1; class = Fixnum; object_id = 3; v >> 1
= 1
a == b => true

And a.equal?(b) is also true.

Both “a” and “b” have their respective values held as immediate values
(embedded in their object_id’s), but they are NOT the same thing
because they’re ultimately held in their respective entries in the
symbol table.

But the symbol table, which contains :a and :b, is not the arbiter of
what constitutes the object 1. The object 1 exists independently of
the symbol table. You can create bindings between that object and one
or more identifiers, but you can do that with any object.

So, object_id’s for Fixnum’s are synthetic. To think
that those object_id’s point to a location in a memory area that
stores the 32-bit 000...001 (in a 32-bit machine/OS) is to contradict
the meaning of immediacy and defeat the very efficiency that immediate
values offer.

I don't think object id's exactly point anywhere. Objects happen to
have unique ids, all of which are synthetic in the sense that they
are, themselves, not the object.

2. Now please consider the following supplement to the statements
above:

a += 1; show (a) => Got 2; class = Fixnum; object_id = 5; v >> 1
= 2

For a += 1 you could substitute anything, like a = 300. It's a
completely new assignment, and completely obliterates any previous
binding.

show (a) => Got 2; class = Fixnum; object_id = 5; v >> 1 = 2
show (b) => Got 1; class = Fixnum; object_id = 3; v >> 1 = 1

The assignment of “a += 1” to “a” changed a’s object_id to embed a new
value: 2.

I'm not sure what you mean by the object_id embedding a value. I would
forget about object_id's, and just look at the objects.

Despite that change of 1 to 2 in a’s object, “b” remains
set to 1. “b” did not suffer the calamity of a universal change of
all Fixnum 1’s to 2’s.

But there is no "a's object" across multiple assignments. The
identifier a has absolutely no continuity of consciousness, so to
speak. It's a reusable, disposable, ad hoc label that can be glued on
to any number of objects in succession. The identifier itself does not
maintain state, and does not "know" how many times it has been used.

   a = "hi"
   a = "bye"

The second line has absolutely no relation to, or dependency on, the
first. And a += 1 is, essentially, just shorthand for a = a + 1 (i.e.,
all the +=, -=, etc. operators are assignment operators).

So when you do a += 1, you're explicitly saying that you are
discarding any previous binding of a, and creating a new one. Of
course, you can only use this shortcut if a has a + method. But it's
an assignment nonetheless; the calling of the method is not, itself,
an assignment operation. You could equally do:

   b = a + 1
   a = b

3. Conclusion:

a += 1 is equivalent to a++’s natural meaning. In fact, we further

"Natural"? :slight_smile:

supplement the above statements with:

class Fixnum
def pp # We can’t define ++ because of a compiler restriction.
   self + 1
end
end

a=1; show(a.pp) => Got 2; class = Fixnum; object_id = 5; v >> 1
= 2
show(b) => Got 1; class = Fixnum; object_id = 3; v >> 1 = 1

Furthermore, pp works fine on the boundary condition for Fixnum’s on a
common 32-bit cpu/OS, i.e. 2**30-1:

a = 2**30-1; show (a) => Got 1073741823; class = Fixnum; object_id
= 2147483647; v >> 1 = 1073741823
a = 2**30; show (a) => Got 1073741824; class = Bignum; object_id =
22737670; v >> 1 = 11368835

So x++ works fine in the form of pp for positive Fixnum’s. I assume
it’ll work fine for non-positives, also.. A compiler change to allow
“def ++” is necessary to finally add ++ to Fixnum.

I know we've been around the block a few times in this thread already,
but the bottom line is that method calls don't affect local variable
bindings. The parser could presumably be trained to treat ++ as an
assignment operator, but Matz's view of this has always been that he
doesn't want assignment semantics to be delivered in something that
looks like a non-assignment idiom from other languages.

The most important example, I think, is this one:

str = "hi"

=> "hi"

str.object_id

=> 1309270

str.succ!

=> "hj"

str

=> "hj"

str.object_id

=> 1309270

a = 1

=> 1

a.object_id

=> 3

a.succ!

NoMethodError: undefined method `succ!' for 1:Fixnum

You can't increment a in place because the messages you send to a
(like: "Increment yourself in place!") are actually being delivered
to an object, not an identifier.

In that sense, the fact that the identifier holds an immediate value
is actually of secondary interest. Even if it didn't, you'd still be
sending a message to an object. The final destination of a message is
never an identifier; it's always an object. So what you're asking for
has to make complete sense in terms of the object.

David

···

On Wed, 4 Nov 2009, RichardOnRails wrote:

--
The Ruby training with D. Black, G. Brown, J.McAnally
Compleat Jan 22-23, 2010, Tampa, FL
Rubyist http://www.thecompleatrubyist.com

David A. Black/Ruby Power and Light, LLC (http://www.rubypal.com)

Rajinder Yadav wrote:
[...]

can you extol

(Not what that word means.)

your knowledge on me about what method_missing is doing?

http://www.ruby-doc.org/docs/ProgrammingRuby/html/ref_c_object.html#Object.method_missing

Best,

···

--
Marnen Laibow-Koser
http://www.marnen.org
marnen@marnen.org
--
Posted via http://www.ruby-forum.com/.

* Robert Klemme <shortcutter@googlemail.com> (23:19) schrieb:

Yes - and in C++ you can have it otherwise:

robert@fussel:~$ g++ x.cc && ./a.out
a++=1
a=2
b=2
robert@fussel:~$ cat x.cc

#include <stdio.h>

int main( int argc, const char* argv[] )
{
  int a = 1;
  int &b = a;
  printf("a++=%d\n", a++);
  printf("a=%d\n", a);
  printf("b=%d\n", b);
  return 0;
}

No, you can't:

$ ./ab
b: 2 @ 0xbfe413f8

$ cat ab.cc
#include <iostream>

int main(void) {
  int a = 1;
  int &b = a;
  a++;
  std::cout << "a: " << a << " @ " << &a << std::endl;
  std::cout << "b: " << b << " @ " << &b << std::endl;
  return 0;
}

There is only one variable, b is just another name for it.

mfg, simon .... l

···

a: 2 @ 0xbfe413f8

I think it would make more sense, if you were going to define a "++"
syntax for Ruby, to use "a.succ" rather than "a+1", and if you are
going to create syntax which does an assignment but returns the
pre-assignment value of the variable receiving the assignment, I'd go
further and include a more general form for that, say ":=", such that
"a := b" is equivalent to "(_ = a),(a = b), _" and then define postfix
"++" such that "a++" is "a := a.succ" and prefix "++" such that "++a"
is equivalent to "a = a.succ".

···

On Fri, Oct 30, 2009 at 3:20 PM, Robert Klemme <shortcutter@googlemail.com> wrote:

On 10/30/2009 08:03 PM, Rick DeNatale wrote:

On Fri, Oct 30, 2009 at 11:05 AM, Robert Klemme >> <shortcutter@googlemail.com> wrote:

2009/10/30 RichardOnRails <RichardDummyMailbox58407@uscomputergurus.com>:

I'll correct my errors and probably have a new theory subsequently.

IMHO the story goes like this: absence of postfix ++ and -- is a
consequence of the fact that numeric types are immutable in Ruby which
makes an assignment necessary for these operators. Although that
would be doable, it would not immediately be obvious when looking at
"foo++". On the other side, "foo += 1" makes the assignment obvious
while still being pretty concise (you do not have to write "foo = foo
+ 1").

I think that theres a more fundamental problem with ++ in a language
like ruby, which has to do with the difference between objects and
variables.

The c ++ and -- operators change a variable, NOT a value.

How their behavior is defined is completely up to the language designer.
You could make "a++" syntactic sugar for

(_tmp = a; a = a + 1; _tmp)

in the same way as "a += 1" is syntactic sugar for "a = a + 1" or "a ||= 10"
is syntactic sugar for "a || a = 10". In fact the sequence in brackets
above would be a completely reasonable way to do it in Ruby: you could use
"a++" in a similar way as in C++ and Java without sacrificing Fixnum's
immutability.

How their behavior is defined is completely up to the language designer.
You could make "a++" syntactic sugar for

(_tmp = a; a = a + 1; _tmp)

in the same way as "a += 1" is syntactic sugar for "a = a + 1" or "a ||= 10"
is syntactic sugar for "a || a = 10". In fact the sequence in brackets
above would be a completely reasonable way to do it in Ruby: you could use
"a++" in a similar way as in C++ and Java without sacrificing Fixnum's
immutability.

And I would argue that you still can't implement ++ for fixnum since
there isn't a ++ method, any more than there is a += method.

But: you would hide the assignment in the syntactic sugared version and this
could lead to unexpected behavior, like

Which I think gets to the fundamental difference.

In C/C++ an integer variable is just a bit-string of a particular
length interpreted as a signed (probably 2s complement) integer, and
++ is a operator on the variable which twiddles those bits.

In Ruby and languages of its ilk, a variable is a reference to an
object, and can only be modified by an assignment, not by a method of
the object it happens to be referencing at the moment, whether that
object is mutable or not.

···

On Fri, Oct 30, 2009 at 6:20 PM, Robert Klemme <shortcutter@googlemail.com> wrote:

On 10/30/2009 08:03 PM, Rick DeNatale wrote:

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Why this wierd semantic? Because it the original use case was for
pointers rather than integers, and it goes back to C originating
originally as a kind of high level assembly language for the DEC
PDP-11 which had postincrement and predecrement addressing modes used
for stepping through strings or arrays.

Apparently apocryphal -- the increment usage predates the PDP 11 port
of C. (Interestingly, there's now a ton of sources repeating the story,
but so far as I know, the canonical answer from Ritchie and Thompson
was that the increment operator predates C proper, and thus the PDP 11
work.)

Because pre-ANSI C allowed easy spoofing/overlay of types, it also
worked for integers and was used in contexts like for loops
    for(i = 0; i < max;i++)

It is not because of spoofing or overlay of types that this worked,
but because the operator's defined for all types.

If you want the real semantics of the C/C++ post-increment operator,
I'm afraid you'll have to look for it in a C family language, not an
object reference semantic language like Ruby.

This part, though, I totally agree with. It's not coherent to imagine a
++ operator, especially a postincrement, working in a Ruby-like language.

-s

···

On 2009-11-04, Rick DeNatale <rick.denatale@gmail.com> wrote:
--
Copyright 2009, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

Tony Arcieri wrote:

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

I think that theres a more fundamental problem with ++ in a language
like ruby, which has to do with the difference between objects and
variables.

Personally I see nothing interesting about the behavior of ++ in any mutable
state language.

Now, consider not immutable objects, but defining ++ for a mutable
object. I've named the method plus_plus instead of ++ since I can do
the former, but not the latter.

How is ++ any different from << except for << taking an argument? (given
hypothetical C-like ++ behavior)

Maybe I am missing something but how would one print a variable and increment it with the same statement? In C one would just write printf ("%i/n", x++). I haven't seen any easy way to do this with Ruby. Using << or +=1 you have to have a separate statement for the assignment. So instead of having something like:
   i = 1
   while (i < 10)
     puts i++
   end
you have to have:
   i = 1
   while (i< 10)
     puts i; i +=1
   end
I can see a reason for not being able to do 2++, but not i++.

···

On Fri, Oct 30, 2009 at 12:03 PM, Rick DeNatale <rick.denatale@gmail.com>wrote:

There is already extensive precedent in Ruby for destructive method calls
that mutate state, and they all lead to the same confusion.

There is nothing interesting with Ruby in this regard, except that Ruby does
seem to go out of its way to do things immutably by default, which, in my
opinion, is pretty cool. But in the end Ruby is still very much a mutable
state language.

I'm not going to run the experiment, but I believe that if the

int &b = a;

were changed to

int b = a;

Then the result would be the same as in Robert's 'surprising' ruby example.

Which only points out the different in meaning between a C 'reference'
variable, which aliases another variable, and the concept of a ruby
variable as a reference to an object.

And no, I don't think that adding syntactic sugar to Ruby to make a++
the same as either

a += 1
or
a = a.succ

is a good idea.

As a matter of fact, neither of this is REALLY the same as a++, since
things like

b = a++

should assign the ORIGINAL value of a to b, as opposed to

b = ++a

Things like post and pre increment/decrement operators in C like
languages are best reserved to languages with the same basic
structure.

To my mind they are akin to the different rules for gender, and
agreement in different families of languages.

···

On Sat, Oct 31, 2009 at 1:35 PM, Simon Krahnke <overlord@gmx.li> wrote:

* Robert Klemme <shortcutter@googlemail.com> (23:19) schrieb:

Yes - and in C++ you can have it otherwise:

robert@fussel:~$ g++ x.cc && ./a.out
a++=1
a=2
b=2
robert@fussel:~$ cat x.cc

#include <stdio.h>

int main( int argc, const char* argv[] )
{
int a = 1;
int &b = a;
printf("a++=%d\n", a++);
printf("a=%d\n", a);
printf("b=%d\n", b);
return 0;
}

No, you can't:

$ ./ab
a: 2 @ 0xbfe413f8
b: 2 @ 0xbfe413f8

$ cat ab.cc
#include <iostream>

int main(void) {
int a = 1;
int &b = a;
a++;
std::cout << "a: " << a << " @ " << &a << std::endl;
std::cout << "b: " << b << " @ " << &b << std::endl;
return 0;
}

There is only one variable, b is just another name for it.

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Yes, maybe you're missing that I support a unary ++ operator :slight_smile:

I can see the wisdom in not having it there to begin with though. I see the
++ operator as something almost inextricably tied to for loops in C. Ruby
provides better looping mechanisms, like the various Enumerable methods that
take blocks! Perhaps Matz didn't include a unary ++ operator as
encouragement to use better looping constructs in your code. If that's the
case, I think he certainly succeeded.

···

On Tue, Nov 3, 2009 at 10:30 PM, Michael W. Ryder <_mwryder55@gmail.com>wrote:

Maybe I am missing something

--
Tony Arcieri
Medioh/Nagravision