Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

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

14 views
Skip to first unread message

RichardOnRails

unread,
Oct 29, 2009, 9:18:27 PM10/29/09
to
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

RichardOnRails

unread,
Oct 30, 2009, 9:42:24 AM10/30/09
to
On Oct 29, 9:18 pm, RichardOnRails

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

Robert Klemme

unread,
Oct 30, 2009, 11:05:10 AM10/30/09
to
2009/10/30 RichardOnRails <RichardDummy...@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 end
http://blog.rubybestpractices.com/

lith

unread,
Oct 30, 2009, 1:51:45 PM10/30/09
to
> 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 ...

Rajinder Yadav

unread,
Oct 30, 2009, 2:41:03 PM10/30/09
to
On Fri, Oct 30, 2009 at 1:51 PM, lith <mini...@gmail.com> wrote:
>> 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

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?

>    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

Rick DeNatale

unread,
Oct 30, 2009, 3:03:33 PM10/30/09
to
On Fri, Oct 30, 2009 at 11:05 AM, Robert Klemme
<short...@googlemail.com> wrote:
> 2009/10/30 RichardOnRails <RichardDummy...@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.

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

Marnen Laibow-Koser

unread,
Oct 30, 2009, 4:32:25 PM10/30/09
to
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
mar...@marnen.org
--
Posted via http://www.ruby-forum.com/.

Robert Klemme

unread,
Oct 30, 2009, 6:19:10 PM10/30/09
to
On 10/30/2009 08:03 PM, Rick DeNatale wrote:
> On Fri, Oct 30, 2009 at 11:05 AM, Robert Klemme
> <short...@googlemail.com> wrote:
>> 2009/10/30 RichardOnRails <RichardDummy...@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.

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:~$

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

Simon Krahnke

unread,
Oct 31, 2009, 1:16:19 PM10/31/09
to
* Robert Klemme <short...@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.

mfg, simon .... l

Christopher Dicely

unread,
Oct 31, 2009, 2:02:32 PM10/31/09
to

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

Rick DeNatale

unread,
Oct 31, 2009, 5:19:01 PM10/31/09
to
On Fri, Oct 30, 2009 at 6:20 PM, Robert Klemme
<short...@googlemail.com> wrote:
> On 10/30/2009 08:03 PM, Rick DeNatale wrote:

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

Rick DeNatale

unread,
Oct 31, 2009, 5:29:49 PM10/31/09
to

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.

RichardOnRails

unread,
Nov 3, 2009, 10:24:23 PM11/3/09
to
On Oct 30, 11:05 am, Robert Klemme <shortcut...@googlemail.com> wrote:
> 2009/10/30 RichardOnRails <RichardDummyMailbox58...@uscomputergurus.com>:

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

Tony Arcieri

unread,
Nov 3, 2009, 11:14:53 PM11/3/09
to
[Note: parts of this message were removed to make it a legal post.]

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

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

--
Tony Arcieri
Medioh/Nagravision

Rick DeNatale

unread,
Nov 3, 2009, 11:17:04 PM11/3/09
to
On Tue, Nov 3, 2009 at 10:25 PM, RichardOnRails
<RichardDummy...@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.

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.

Seebs

unread,
Nov 3, 2009, 11:24:59 PM11/3/09
to
On 2009-11-04, Rick DeNatale <rick.d...@gmail.com> wrote:
> 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
--
Copyright 2009, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

Michael W. Ryder

unread,
Nov 4, 2009, 12:29:45 AM11/4/09
to
Tony Arcieri wrote:
> [Note: parts of this message were removed to make it a legal post.]
>
> On Fri, Oct 30, 2009 at 12:03 PM, Rick DeNatale <rick.d...@gmail.com>wrote:
>
>> 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++.

Tony Arcieri

unread,
Nov 4, 2009, 12:38:55 AM11/4/09
to
[Note: parts of this message were removed to make it a legal post.]

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

> Maybe I am missing something
>

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

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.

--
Tony Arcieri
Medioh/Nagravision

Charles Oliver Nutter

unread,
Nov 4, 2009, 1:58:39 AM11/4/09
to
Of course I had to jump in here.

Yes, a++ and ++a could easily be rewritten by the parser into the
appropriate increment+set of a and the expression either returns the
incremented value or the non-incremented value. And I would like to
see that added. It doesn't fundamentally change the expectations of
the programmer, and it provides a one-character-shorter version of
a+=1. There's really no reason it shouldn't be added, because even in
Java or C, you are *never* modifying arbitrary references to that
value...you are *always* re-assigning the value a given variable
points to.

This example:

a = 1
b = a
a++

Would cause exactly the same results in every language I've worked
with...b would be 1 and a would be 2. The ++ operator never modifies a
value, it modifies what value the variable has assigned to it. If it
were modifying a value, then using ++ to bump a pointer through memory
offsets would have horrible side effects for anyone else assigned that
pointer value.

I have seen no convincing argument as to why ++ is not supported in Ruby.

- Charlie

lith

unread,
Nov 4, 2009, 4:24:57 AM11/4/09
to
> Yes, a++ and ++a could easily be rewritten by the parser into the
> appropriate increment+set of a and the expression

Wouldn't it be cool if ruby had macros?

Robert Klemme

unread,
Nov 4, 2009, 5:13:49 AM11/4/09
to
2009/11/4 lith <mini...@gmail.com>:

>> Yes, a++ and ++a could easily be rewritten by the parser into the
>> appropriate increment+set of a and the expression
>
> Wouldn't it be cool if ruby had macros?

No.

Gavin Sinclair

unread,
Nov 4, 2009, 5:50:35 AM11/4/09
to
On Nov 4, 5:58 pm, Charles Oliver Nutter <head...@headius.com> wrote:
>
> There's really no reason it shouldn't be added [...]

There's no reason it _should_ be added. That's the reason it
shouldn't be.

> I have seen no convincing argument as to why ++ is not supported in Ruby.

You've got the onus the wrong way around.

And adding C-like operators based on a partiular assembly language to
any 21st century language, especially a high-level one, just seems
absurd!

Extra documentation so we can save three characters (a++ instead of a
+= 1) in a rare use case? No thanks!

--
Gavin Sinclair

David A. Black

unread,
Nov 4, 2009, 7:14:44 AM11/4/09
to
Hi --

It would, I think, be quite anomalous, since it would be the only case
(that I can think of anyway) of an assignment expression that didn't
look and feel like an assignment expression.

I'm also not sure what problem it would be solving, other than adding
to the "make <language> users feel at home in Ruby" effect. But I tend
to think that Ruby should move away from, not towards, doing things
for exclusively that reason.


David

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

Robert Klemme

unread,
Nov 4, 2009, 7:26:48 AM11/4/09
to
2009/11/4 David A. Black <dbl...@rubypal.com>:

> Hi --
>
> On Wed, 4 Nov 2009, Charles Oliver Nutter wrote:

>> I have seen no convincing argument as to why ++ is not supported in Ruby.
>
> It would, I think, be quite anomalous, since it would be the only case
> (that I can think of anyway) of an assignment expression that didn't
> look and feel like an assignment expression.
>
> I'm also not sure what problem it would be solving, other than adding
> to the "make <language> users feel at home in Ruby" effect. But I tend
> to think that Ruby should move away from, not towards, doing things
> for exclusively that reason.

+2 (Thanks for the well formulated reasoning, David!)

Rick DeNatale

unread,
Nov 4, 2009, 9:07:39 AM11/4/09
to

Certainly it could be implemented in an extension to the language as
syntactic sugar much as += and it's family.

But I maintain, that it can't be implemented as a method, any more
than += or ||= could be.

If Matz deigned to do such a language change, I'd certainly feel free
to ignore it. <G>

I can't help but think of Alan Perlis' quip that "syntactic sugar
causes cancer of the semicolons"

Marnen Laibow-Koser

unread,
Nov 4, 2009, 9:31:46 AM11/4/09
to
Rick Denatale wrote:
[...]

> Certainly it could be implemented in an extension to the language as
> syntactic sugar much as += and it's family.
>
> But I maintain, that it can't be implemented as a method, any more
> than += or ||= could be.

I believe you are quite wrong. If a destructive function like gsub! can
be implemented as a method, then I see no reason that +=, |=, or postfix
++ couldn't be.

>
> If Matz deigned to do such a language change, I'd certainly feel free
> to ignore it. <G>

Well, as others have pointed out, Ruby's preference for iterators rather
than loops makes ++ a lot less useful. I use it a lot in PHP, but I
really haven't missed it in Ruby.

>
> I can't help but think of Alan Perlis' quip that "syntactic sugar
> causes cancer of the semicolons"

Cute. Of course, at some level, every programming language is syntactic
sugar...

Best,

Seebs

unread,
Nov 4, 2009, 9:37:52 AM11/4/09
to
On 2009-11-04, Marnen Laibow-Koser <mar...@marnen.org> wrote:
> I believe you are quite wrong. If a destructive function like gsub! can
> be implemented as a method, then I see no reason that +=, |=, or postfix
> ++ couldn't be.

gsub! is implemented as a method on objects which contain data. ++ would
have to be implemented as a method on objects which ARE their data -- which
have no distinction between the object and its "contents".

gsub! can work because somewhere inside the object there is a hunk of storage
which is separate from the object itself. Fixnum has no such storage to
refer to.

lith

unread,
Nov 4, 2009, 9:56:07 AM11/4/09
to
> gsub! can work because somewhere inside the object there is a hunk of storage
> which is separate from the object itself.  Fixnum has no such storage to
> refer to.

I don't think ruby makes the distinction between native types &
objects à la java. I don't know the ruby source but from a glance at
numeric.c[1], I'd say it is handled as VALUE/ruby object like any
other object. All those numeric methods seem to convert the VALUE to c
numbers, do what they are supposed to do and then convert them back
again. Please correct me if I'm wrong and if you know the ruby source
code.

I don't think ruby is in need of such an operator but I don't see why
ruby shouldn't have macros to let people fake such a thing if they
deem it necessary.


[1] http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/numeric.c?view=markup

Yukihiro Matsumoto

unread,
Nov 4, 2009, 10:59:41 AM11/4/09
to
Hi,

In message "Re: Ruby doesn't implement x++ for Fixnum's because ???"


on Wed, 4 Nov 2009 23:31:46 +0900, Marnen Laibow-Koser <mar...@marnen.org> writes:

|I believe you are quite wrong. If a destructive function like gsub! can
|be implemented as a method, then I see no reason that +=, |=, or postfix
|++ couldn't be.

Only if you accept the language that can change the value of 1 to 2.
I don't.

matz.

Seebs

unread,
Nov 4, 2009, 11:49:18 AM11/4/09
to
On 2009-11-04, lith <mini...@gmail.com> wrote:
>> gsub! can work because somewhere inside the object there is a hunk of storage
>> which is separate from the object itself. �Fixnum has no such storage to
>> refer to.

> I don't think ruby makes the distinction between native types &

> objects � la java.

Everything is an object.

Not every object contains separate storage.

When you write "a = 1; b = 1;", a and b do not refer to two separate objects
which happen to have the same numeric value; they refer to a single object
which has an immutable numeric value. You can't increment that value.

Seebs

unread,
Nov 4, 2009, 11:50:26 AM11/4/09
to

Hmph. Fortran can change constants, why's Ruby so much less powerful?

:)

-s
p.s.: Thanks much for providing such an enjoyable language.

Tony Arcieri

unread,
Nov 4, 2009, 12:11:50 PM11/4/09
to
[Note: parts of this message were removed to make it a legal post.]

On Wed, Nov 4, 2009 at 3:55 AM, Gavin Sinclair <gsin...@gmail.com> wrote:

> You've got the onus the wrong way around.
>
> And adding C-like operators based on a partiular assembly language to
> any 21st century language, especially a high-level one, just seems
> absurd!
>
> Extra documentation so we can save three characters (a++ instead of a
> += 1) in a rare use case? No thanks!
>

I think you're missing why ++ could be useful, and it's precisely because
Ruby is a "21st century language"

The ++ operator, far more than just being syntactic sugar for +=1, would
allow you to send an "increment" message to any object, which would change
its value in place, i.e.

def ++
incrementing_logic_goes_here
end

I could see this as being handy

--
Tony Arcieri
Medioh/Nagravision

Martin DeMello

unread,
Nov 4, 2009, 12:23:21 PM11/4/09
to
On Wed, Nov 4, 2009 at 10:41 PM, Tony Arcieri <to...@medioh.com> wrote:
>
> The ++ operator, far more than just being syntactic sugar for +=1, would
> allow you to send an "increment" message to any object, which would change
> its value in place, i.e.

And how exactly would you change the value of 1 in place?

martin

RichardOnRails

unread,
Nov 4, 2009, 12:59:29 PM11/4/09
to

Hi David,

First, Thank you for The Well-Grounded Rubyist. I study like other
pour over scriptures or the Koran. Your topics are well chose,
beautifully explicated. And Manning adding typesetting that enhanced
the your work.

I started this thread because some of your comments on page 54, e.g.
"The un-reference ..." were a blemish among your excellent analyses.
The fact that Robert Klemme, whom I also respect highly as a Rubyist,
agrees with you gives me pause.

But nevertheless, I maintain that my corrected post of today refutes
such claims as "... any object that's represented as an immediate
value is always the same object." Russel & Whitehead dealt with this
kind of issue perhaps a century ago when the defined the first Natural
Number, 1, as "the set of all sets that are in one-to-one
correspondence with the set containing the Null Set." Plato dealt with
this in The Parable of the Caves" with the claim that allegedly
concrete things were merely reflections of the "real" objects.

I'm not clamoring for a Ruby implementation. I only posted my
analysis on this issue to get other people's opinions. And I find it
hard compose a mistake free exposition, e.g. the last code lines in
yesterday evening's post:

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

should have read:

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

show(a.pp) => Got 1073741824; class = Bignum; object_id =
22738520; v >> 1 = 11369260 # Of course, "v >> 1" is irrelevant
here

to make the point that "pp" crossed the Fixnum/Bignum boundary
smoothly.

Bottom line: Please keep up you great work! I appreciate it very
much!

Best wishes,
Richard

Tony Arcieri

unread,
Nov 4, 2009, 1:16:54 PM11/4/09
to
[Note: parts of this message were removed to make it a legal post.]

On Wed, Nov 4, 2009 at 10:23 AM, Martin DeMello <martin...@gmail.com>wrote:

> And how exactly would you change the value of 1 in place?
>

You don't. Are you insinuating the behavior of Fixnums isn't already
special cased to begin with?

--
Tony Arcieri
Medioh/Nagravision

Tony Arcieri

unread,
Nov 4, 2009, 1:18:19 PM11/4/09
to
[Note: parts of this message were removed to make it a legal post.]

On Wed, Nov 4, 2009 at 10:23 AM, Martin DeMello <martin...@gmail.com>wrote:

> And how exactly would you change the value of 1 in place?
>

Another way to look at it: does Fixnum#+ change the value of its receiver?

--
Tony Arcieri
Medioh/Nagravision

Paul Smith

unread,
Nov 4, 2009, 1:21:11 PM11/4/09
to
On Wed, Nov 4, 2009 at 6:16 PM, Tony Arcieri <to...@medioh.com> wrote:
> On Wed, Nov 4, 2009 at 10:23 AM, Martin DeMello <martin...@gmail.com>wrote:
>
>> And how exactly would you change the value of 1 in place?
>>
>
> You don't.  Are you insinuating the behavior of Fixnums isn't already
> special cased to begin with?

a = 1

a.class #Fixnum

a++ # a is now 2

1.class #Fixnum

1++ # Illegal

So although a is a Fixnum, and 1 is a Fixnum, they respond to ++ differently?

>
> --
> Tony Arcieri
> Medioh/Nagravision
>

--
Paul Smith
http://www.nomadicfun.co.uk

pa...@pollyandpaul.co.uk

RichardOnRails

unread,
Nov 4, 2009, 2:04:57 PM11/4/09
to
On Nov 4, 9:37 am, Seebs <usenet-nos...@seebs.net> wrote:
> On 2009-11-04, Marnen Laibow-Koser <mar...@marnen.org> wrote:
>
> > I believe you are quite wrong.  If a destructive function like gsub! can
> > be implemented as a method, then I see no reason that +=, |=, or postfix
> > ++ couldn't be.
>
> gsub! is implemented as a method on objects which contain data.  ++ would
> have to be implemented as a method on objects which ARE their data -- which
> have no distinction between the object and its "contents".
>
> gsub! can work because somewhere inside the object there is a hunk of storage
> which is separate from the object itself.  Fixnum has no such storage to
> refer to.
>
> -s
> --
> Copyright 2009, all wrongs reversed.  Peter Seebach / usenet-nos...@seebs.nethttp://www.seebs.net/log/<-- lawsuits, religion, and funny pictureshttp://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!


> ++ would have to be implemented as a method on objects which ARE their data

Not true. Check out the following, step by step:

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

class Fixnum


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

These lines show that a & b values are stored in there object_ids held
in the symbol table.
Don’t believe it? Read more.
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

Appending these lines shows that a & b values are distinct.
That is, after incrementing, a =2, b is unchanged; b is not
impacted by a’s change
a += 1; show (a) => Got 2; class = Fixnum; object_id = 5; v >> 1
= 2
show (b) => Got 1; class = Fixnum; object_id = 3; v >> 1 = 1

Appending these lines shows the ++’s alias pp works just find


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

Appending these lines show that ++ crosses the Fixnum/Bignum boundary


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

22738520; v >> 1 = 11369260 # “v >> 1” is irrelevant, of course.

Do you agree?

Best wishes,
Richard

Walton Hoops

unread,
Nov 4, 2009, 2:13:13 PM11/4/09
to
> -----Original Message-----
> From: bas...@gmail.com [mailto:bas...@gmail.com] On Behalf Of Tony
> Arcieri

> wrote:
> I think you're missing why ++ could be useful, and it's precisely
> because
> Ruby is a "21st century language"
>
> The ++ operator, far more than just being syntactic sugar for +=1,
> would
> allow you to send an "increment" message to any object, which would
> change
> its value in place, i.e.
>
> def ++
> incrementing_logic_goes_here
> end
>
> I could see this as being handy

But you already can with the mechanics of the language that are already
present!

irb(main):003:0> i=15
=> 15
irb(main):004:0> i=i.succ
=> 16
irb(main):005:0> i="15"
=> "15"
irb(main):006:0> i=i.succ
=> "16"
irb(main):007:0> i=1.2
=> 1.2
irb(main):008:0> i=i.succ
NoMethodError: undefined method `succ' for 1.2:Float
from (irb):8
from /usr/local/bin/irb:12:in `<main>'

In an object that it makes sense to increment, define the #succ method!
It's that easy!


Seebs

unread,
Nov 4, 2009, 2:13:10 PM11/4/09
to
On 2009-11-04, RichardOnRails <RichardDummy...@USComputerGurus.com> wrote:
> class Fixnum
> def pp # We can?t define ++ because of a compiler restriction.

> self + 1
> end
> end

This doesn't seem to do the right thing.

a = 1
a.pp

Is a now 2? If not, you haven't implemented an increment operator.

> Appending these lines shows that a & b values are distinct.
> That is, after incrementing, a =2, b is unchanged; b is not

> impacted by a?s change


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

Right. You've changed which object a refers to, because you've reassigned
a.

> Appending these lines shows the ++?s alias pp works just find


> 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

Not the same. The key is that, after "a += 1", not only do you get 2,
but a is now 2.

> Do you agree?

No.

For "a.pp" to be the same as a++ in other languages, you'd have to do:

a = 1; a.pp; show(a) => Got 2

If you don't get a "2" by using a.pp, it's not an increment, just a "one
more than".

Consider a loop:

a = 1
while ((a += 1) < 10) do
puts a
end

Now, try:

a = 1
while (a.pp < 10) do
puts a
end

Doesn't do the same thing.

-s
--

Martin DeMello

unread,
Nov 4, 2009, 2:16:16 PM11/4/09
to
On Wed, Nov 4, 2009 at 11:46 PM, Tony Arcieri <to...@medioh.com> wrote:
> On Wed, Nov 4, 2009 at 10:23 AM, Martin DeMello <martin...@gmail.com>wrote:
>
>> And how exactly would you change the value of 1 in place?
>>
>
> You don't.  Are you insinuating the behavior of Fixnums isn't already
> special cased to begin with?

yes, i see your point, but consider:

a = Foo.new()
b = a
c = 42
d = c
a++
p b
c++
p d

martin


>
> --
> Tony Arcieri
> Medioh/Nagravision
>

RichardOnRails

unread,
Nov 4, 2009, 2:20:04 PM11/4/09
to

Hi Matz,

Thank you very much for your brilliant and enormous efforts in
creating Ruby and offering to the programming world as gift.

> Only if you accept the language that can change the value of 1 to 2.

I know that you know Ruby extremely well. But I have written the
following tests on this issue of whether "1" ever gets changed to
"2". I assume you have not looked at my post yesterday on this
issue. I'd be honored if you'd
look at the following comments and code and point out anything you
view as erroneous.

BTW, I'm not advocating x++ for Ruby. I'm just trying to understand
whether Ruby would literally change 1 to 2 as opposed to change a
variable that contains 1 to subsequently contain 2.

Best wishes,
Richard

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

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


self + 1
end
end

These lines show that a & b values are stored in their object_ids held


in the symbol table.
Don’t believe it? Read more.

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

Appending these lines shows that a & b values are distinct.


That is, after incrementing, a =2, b is unchanged; b is not

impacted by a’s change


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

Appending these lines shows the ++’s alias pp works just find


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

Appending these lines show that ++ crosses the Fixnum/Bignum boundary

Aldric Giacomoni

unread,
Nov 4, 2009, 3:00:26 PM11/4/09
to
RichardOnRails wrote:

> BTW, I'm not advocating x++ for Ruby. I'm just trying to understand
> whether Ruby would literally change 1 to 2 as opposed to change a
> variable that contains 1 to subsequently contain 2.

I am confused.
irb(main):001:0> 1.succ
=> 2
irb(main):002:0> 1.object_id
=> 3
irb(main):003:0> 1.succ.object_id
=> 5
irb(main):004:0>

Is that good enough? If not, I'd recommend taking a look at...
irb(main):004:0> 1.class
=> Fixnum

Fixnum .. Fixed number? :)

Martin DeMello

unread,
Nov 4, 2009, 3:18:02 PM11/4/09
to
On Thu, Nov 5, 2009 at 12:55 AM, RichardOnRails
<RichardDummy...@uscomputergurus.com> wrote:
>
> BTW,  I'm not advocating x++ for Ruby.  I'm just trying to understand
> whether Ruby would literally change 1 to 2 as opposed to change a
> variable that contains 1 to subsequently contain 2.

Variables don't contain values, they refer to objects. That's the
fundamental difference. So if you say, for instance

a = "hello world"
a.upcase!
a #=> "HELLO WORLD"

the message "upcase!" is sent to the *object* "hello world", not the
variable a. To see this:

a = "hello world"
b = a
a.upcase!
a #=> "HELLO WORLD"
b #=> "HELLO WORLD"

Fixnums are immutable objects; you can't have any method that changes
their value. Hence no ++

martin

Michael W. Ryder

unread,
Nov 4, 2009, 3:22:45 PM11/4/09
to
But i.succ does Not work in the following:

i = 1
while (i < 10)
puts i.succ
end

the only way to get this to work is to use:
puts i; i = i.succ

which is not as clean as using puts i++.

RichardOnRails

unread,
Nov 4, 2009, 3:29:19 PM11/4/09
to
On Nov 4, 2:13 pm, Seebs <usenet-nos...@seebs.net> wrote:
> Copyright 2009, all wrongs reversed.  Peter Seebach / usenet-nos...@seebs.nethttp://www.seebs.net/log/<-- lawsuits, religion, and funny pictureshttp://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

Hi Peter,

> This doesn't seem to do the right thing.
>
> a = 1
> a.pp
>
> Is a now 2? If not, you haven't implemented an increment operator.

Thanks for this question. You're so right. I couldn't see it until
you pointed it out.

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


self + 1
end
end

doesn't change self (which Ruby won't allow for Fixnum's!!! Which, of
course, is why your:

a = 1
while (a.pp < 10) do
puts a
end

produces an infinite number of 1's ..., or would if RAM were infinite
and hardware addressing mechanisms were infinite.

I grateful for you taking the time to identify my deficiencies.

Best wishes,
Richard

Seebs

unread,
Nov 4, 2009, 3:37:36 PM11/4/09
to
On 2009-11-04, RichardOnRails <RichardDummy...@USComputerGurus.com> wrote:
> I grateful for you taking the time to identify my deficiencies.

I'd call it an oversight, not a personal failing.

It might make sense to want to be able to do
def pp()
old = self
self = self + 1
old
end

or something similar, but it's not well-defined. The problem is that
fundamentally, when you have two variables, a and b, which both contain
the object 1 (a Fixnum), there's no way to say "I want the object a points
to to change, but not the object b points to" *in a method call*. Because
the method call works on the object, not the variable.

-s
--

Tony Arcieri

unread,
Nov 4, 2009, 3:40:38 PM11/4/09
to
[Note: parts of this message were removed to make it a legal post.]

On Wed, Nov 4, 2009 at 11:21 AM, Paul Smith <pa...@pollyandpaul.co.uk> wrote:

> a = 1
>
> a.class #Fixnum
>
> a++ # a is now 2
>
> 1.class #Fixnum
>
> 1++ # Illegal
>
> So although a is a Fixnum, and 1 is a Fixnum, they respond to ++
> differently?
>

Why would 1++ be illegal? I'd think it would just evaluate to 1.

--
Tony Arcieri
Medioh/Nagravision

Marnen Laibow-Koser

unread,
Nov 4, 2009, 3:46:30 PM11/4/09
to
Michael W. Ryder wrote:
[...]

> But i.succ does Not work in the following:
>
> i = 1
> while (i < 10)
> puts i.succ
> end
>
> the only way to get this to work is to use:
> puts i; i = i.succ
>
> which is not as clean as using puts i++.

This is unidiomatic Ruby. In fact, it's becoming clear to me that just
about *any* use case for postfix ++ is unidiomatic Ruby. The cleanest
way *in Ruby* of doing what you did would be

(1..10).each {|i| puts i}

Incrementing is handled under the hood.

Best,
--
Marnen Laibow-Koser
http://www.marnen.org
mar...@marnen.org

Tony Arcieri

unread,
Nov 4, 2009, 3:48:56 PM11/4/09
to
[Note: parts of this message were removed to make it a legal post.]

On Wed, Nov 4, 2009 at 1:46 PM, Marnen Laibow-Koser <mar...@marnen.org>wrote:

> This is unidiomatic Ruby. In fact, it's becoming clear to me that just
> about *any* use case for postfix ++ is unidiomatic Ruby. The cleanest
> way *in Ruby* of doing what you did would be
>
> (1..10).each {|i| puts i}
>
> Incrementing is handled under the hood.
>

What if it's not?

m = CounterInMemcacheOrSomething.new :foobar
m++

--
Tony Arcieri
Medioh/Nagravision

Marnen Laibow-Koser

unread,
Nov 4, 2009, 4:41:59 PM11/4/09
to
Tony Arcieri wrote:
> On Wed, Nov 4, 2009 at 1:46 PM, Marnen Laibow-Koser
> <mar...@marnen.org>wrote:
>
>> This is unidiomatic Ruby. In fact, it's becoming clear to me that just
>> about *any* use case for postfix ++ is unidiomatic Ruby. The cleanest
>> way *in Ruby* of doing what you did would be
>>
>> (1..10).each {|i| puts i}
>>
>> Incrementing is handled under the hood.
>>
>
> What if it's not?
>
> m = CounterInMemcacheOrSomething.new :foobar
> m++

What semantics do you intend here? I'm not sure I understand.

In any case, you have several perfectly good alternatives:

* use CounterInMemcacheOrSomething.all(:foobar).each{|m| ...}

* define CounterInMemcacheOrSomething#succ! if it's mutable

* or even use m += 1

++ is very useful in C-like languages and PHP. I thought it would be
useful in Ruby too, but I now believe that it wouldn't, since it's only
really good for stepping through structures -- and Ruby handles that
better with iterators.

Walton Hoops

unread,
Nov 4, 2009, 4:44:21 PM11/4/09
to
> -----Original Message-----
> From: Michael W. Ryder [mailto:_mwry...@gmail.com]
> But i.succ does Not work in the following:
>
> i = 1
> while (i < 10)
> puts i.succ
> end
>
> the only way to get this to work is to use:
> puts i; i = i.succ
>
> which is not as clean as using puts i++.

I'd argue it's much, much cleaner. ++ has long been a source
of confusion for C programmers. Consider:

int i = 1;
while (i < 10)
{
printf("%d,",i++);
}

What does it ouput? 1,2,3,4,5,6,7,8,9, or 2,3,4,5,6,7,8,9,10,?

Because we're all experienced C programmers here we of course know
it to be 1,2,3,4,5,6,7,8,9, but it's not uncommon for experienced C
programmers to make mistakes around a++ vs ++a. On the other hand:

int i = 1;
while (i <10)
{
printf("%d,",i);
i+=1;
}

Makes it explicitly clear what is happening. Then consider the ruby
direct ruby translation:

i = 1;
while (i <10)

print "#{i},"
i+=1;
end

Even a non-programmer is going to have a pretty darn clear idea of
what is going on here. Sure it's one line longer but much more
understandable, and therefore cleaner. If there is one thing
playing Perl Golf should have taught all programmers it's that
shorter != better.

Now consider the ruby way:

10.times do |i|
print "#{i},"
end

Some length as the C code, but much more readable. Heck, it's
almost English! Which is part of the beauty of Ruby: It's simple,
natural, readable syntax. I've seen a lot of arguments that it
doesn't fit with ruby's object model, but to me that's not the key
point. ++ doesn't fit with Ruby's elegant syntax.


Tony Arcieri

unread,
Nov 4, 2009, 4:50:10 PM11/4/09
to
[Note: parts of this message were removed to make it a legal post.]

On Wed, Nov 4, 2009 at 2:41 PM, Marnen Laibow-Koser <mar...@marnen.org>wrote:

> What semantics do you intend here? I'm not sure I understand.
>

You can think of it like:

alias_method :++, :increment!

--
Tony Arcieri
Medioh/Nagravision

Yukihiro Matsumoto

unread,
Nov 4, 2009, 4:59:38 PM11/4/09
to
Hi,

In message "Re: Ruby doesn't implement x++ for Fixnum's because ???"

on Thu, 5 Nov 2009 04:25:05 +0900, RichardOnRails <RichardDummy...@USComputerGurus.com> writes:

|BTW, I'm not advocating x++ for Ruby. I'm just trying to understand
|whether Ruby would literally change 1 to 2 as opposed to change a
|variable that contains 1 to subsequently contain 2.

There's no way to modify local variables by sending message in Ruby.

matz.

Michael W. Ryder

unread,
Nov 4, 2009, 5:57:01 PM11/4/09
to
Walton Hoops wrote:
<snip>

> Now consider the ruby way:
>
> 10.times do |i|
> print "#{i},"
> end
>
> Some length as the C code, but much more readable. Heck, it's
> almost English!

Not for me it wasn't. I had to try it to see that it actually works.
My initial impression was that it would print 10 copies of i. I still
don't see where 'i' is incremented so this is one of those "magical"
constructs much like your impression of ++ in C. I would find this much
harder to maintain than the C version.

Marnen Laibow-Koser

unread,
Nov 4, 2009, 6:18:33 PM11/4/09
to
Michael W. Ryder wrote:
> Walton Hoops wrote:
> <snip>
>
>> Now consider the ruby way:
>>
>> 10.times do |i|
>> print "#{i},"
>> end
>>
>> Some length as the C code, but much more readable. Heck, it's
>> almost English!
>
> Not for me it wasn't. I had to try it to see that it actually works.
> My initial impression was that it would print 10 copies of i. I still
> don't see where 'i' is incremented

Well, you do have to know what Numeric#times yields to its block. But
that's easy to look up. (However, it starts from 0, so it's not quite
equivalent to the C.)

> so this is one of those "magical"
> constructs much like your impression of ++ in C.

No. The "magic" is different. In the Ruby version, a quick check in
the API tells you that the counter is incremented each time through the
loop. In the C version, OTOH, you have to think about exactly where
you've put the ++, and whether you really wanted the value before or
after the increment.

> I would find this much
> harder to maintain than the C version.

Only because you apparently are not familiar with common Ruby idioms.
The Ruby version has a lot less to go wrong in it, because the language
transparently handles incrementing the "loop index" at the right time.


>
> Which is part of the beauty of Ruby: It's simple,

Yes. Just don't expect it to be much like C.

Walton Hoops

unread,
Nov 4, 2009, 6:48:53 PM11/4/09
to
> -----Original Message-----
> From: mar...@marnen.org [mailto:mar...@marnen.org]
> >> Now consider the ruby way:
> >>
> >> 10.times do |i|
> >> print "#{i},"
> >> end
> >>
> >> Some length as the C code, but much more readable. Heck, it's
> >> almost English!
> >
>
> Well, you do have to know what Numeric#times yields to its block. But
> that's easy to look up. (However, it starts from 0, so it's not quite
> equivalent to the C.)

Whoop! Good point, that's what I get for not actually testing my code.

Corrected (and even closer to English).

(1..9).each do |i|


print "#{i},"
end

Michael Wrote:
> > Not for me it wasn't. I had to try it to see that it actually works.
> > My initial impression was that it would print 10 copies of i.
> I still don't see where 'i' is incremented

It isn't incremented, at least not in MY code (if you must think in
terms of incrementing variables, then Ruby is incrementing it for me)
See the times method at:
http://ruby-doc.org/core/classes/Integer.html
That kind of looping is a pretty core Ruby concept.

Also the corrected version I wrote above should be a bit clearer. Also
I think your previous programming experience is hurting you here. To you
as (I'm guessing) a C programmer, to progress in a loop, you must increment
modify variable. The average English speaker doesn't think in those terms.

Looking at my most recent example, the English equivalent would be for each
'i' from 1 to 9 print 'i' followed by a comma. Sure, the words may not be
in the precise order, but it comes a darn site closer to natural language than:

int i=1;

Michael W. Ryder

unread,
Nov 4, 2009, 7:08:38 PM11/4/09
to
Walton Hoops wrote:
>> -----Original Message-----
>> From: mar...@marnen.org [mailto:mar...@marnen.org]
>>>> Now consider the ruby way:
>>>>
>>>> 10.times do |i|
>>>> print "#{i},"
>>>> end
>>>>
>>>> Some length as the C code, but much more readable. Heck, it's
>>>> almost English!
>> Well, you do have to know what Numeric#times yields to its block. But
>> that's easy to look up. (However, it starts from 0, so it's not quite
>> equivalent to the C.)
>
> Whoop! Good point, that's what I get for not actually testing my code.
>
> Corrected (and even closer to English).
>
> (1..9).each do |i|
> print "#{i},"
> end
>

That version I understand just looking at it as it is equivalent to a
for loop. Your first version seemed more "magical" since I don't know
where 'i' is getting incremented. At least with C I know where the
incrementing is occurring.

> Michael Wrote:
>>> Not for me it wasn't. I had to try it to see that it actually works.
>>> My initial impression was that it would print 10 copies of i.
>> I still don't see where 'i' is incremented
>
> It isn't incremented, at least not in MY code (if you must think in
> terms of incrementing variables, then Ruby is incrementing it for me)
> See the times method at:
> http://ruby-doc.org/core/classes/Integer.html
> That kind of looping is a pretty core Ruby concept.
>
> Also the corrected version I wrote above should be a bit clearer. Also
> I think your previous programming experience is hurting you here. To you
> as (I'm guessing) a C programmer, to progress in a loop, you must increment
> modify variable. The average English speaker doesn't think in those terms.
>

I started with Fortran in the early 1980's, followed by Basic, Pascal,
Modula 2, and C. For over 25 years I have been mostly programming in
Business Basic. While Ruby has a lot of things going for it I miss some
of the features available in the other languages, especially the built
in curses and file handling in Business Basic.

Gavin Sinclair

unread,
Nov 5, 2009, 5:38:16 AM11/5/09
to
On Nov 5, 4:11 am, Tony Arcieri <t...@medioh.com> wrote:
>
> I think you're missing why ++ could be useful, and it's precisely because
> Ruby is a "21st century language"
>
> The ++ operator, far more than just being syntactic sugar for +=1, would
> allow you to send an "increment" message to any object, which would change
> its value in place, i.e.
>
>   def ++
>     incrementing_logic_goes_here
>   end
>
> I could see this as being handy

What's wrong with

def inc
incrementing_logic_goes_here
end

How is that any different?

Gavin Sinclair

unread,
Nov 5, 2009, 5:42:31 AM11/5/09
to
On Nov 5, 7:22 am, "Michael W. Ryder" <_mwryde...@gmail.com> wrote:
>
> But i.succ does Not work in the following:
>
> i = 1
> while (i < 10)
>    puts i.succ
> end
>
> the only way to get this to work is to use:
>    puts i; i = i.succ
>
> which is not as clean as using puts i++.


Maybe you'll just have to find another way to print the numbers 1 to
10 ;)

Tobias Cohen

unread,
Nov 5, 2009, 6:21:03 AM11/5/09
to

On 05/11/2009, at 1:31 AM, Marnen Laibow-Koser wrote:
> I believe you are quite wrong. If a destructive function like gsub!
> can
> be implemented as a method, then I see no reason that +=, |=, or
> postfix
> ++ couldn't be.

It can be done, if you are willing to make your numbers mutable:

class MutableNum
def initialize n
@n = n
end

def pp
@n += 1
@n - 1
end

def method_missing symbol, *args
@n.method(symbol).call(*args)
end

def to_s
@n.to_s
end
end

a = MutableNum.new 1
puts a.pp #=> 1
puts a #=> 2

Having said that, I agree with others that the post-increment operator
is not needed in Ruby at all.

--
Tobias Cohen
http://tobiascohen.com/

David A. Black

unread,
Nov 5, 2009, 7:54:06 AM11/5/09
to
Hi --

On Thu, 5 Nov 2009, Tony Arcieri wrote:

> On Wed, Nov 4, 2009 at 2:41 PM, Marnen Laibow-Koser <mar...@marnen.org>wrote:
>
>> What semantics do you intend here? I'm not sure I understand.
>>
>
> You can think of it like:
>
> alias_method :++, :increment!

But what would it mean to send the message increment! to, say, the
object 10? In the same vein:

>> 10.succ!
NoMethodError: undefined method `succ!' for 10:Fixnum


David

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

Aldric Giacomoni

unread,
Nov 5, 2009, 8:06:07 AM11/5/09
to
David A. Black wrote:
>
> But what would it mean to send the message increment! to, say, the
> object 10? In the same vein:
>
> >> 10.succ!
> NoMethodError: undefined method `succ!' for 10:Fixnum

I agree with David.. At which point are we completely violating the
principle of least surprise?
A number is a number is a number. It took me all of half an hour to
forget about ++ and I haven't looked back since. I -like- typing +=1
because it, simply put, makes sense.

Tony Arcieri

unread,
Nov 5, 2009, 12:12:27 PM11/5/09
to
[Note: parts of this message were removed to make it a legal post.]

On Thu, Nov 5, 2009 at 3:40 AM, Gavin Sinclair <gsin...@gmail.com> wrote:

> > def ++
> > incrementing_logic_goes_here
> > end
> >
> > I could see this as being handy
>
> What's wrong with
>
> def inc
> incrementing_logic_goes_here
> end
>
> How is that any different?
>

What's wrong with Array#push? Why do we need Array#<<? How is that any
different?

--
Tony Arcieri
Medioh/Nagravision

David A. Black

unread,
Nov 5, 2009, 7:28:26 PM11/5/09
to
Hi--

On Fri, 6 Nov 2009, Tony Arcieri wrote:

> On Thu, Nov 5, 2009 at 3:40 AM, Gavin Sinclair <gsin...@gmail.com> wrote:
>
>>> def ++
>>> incrementing_logic_goes_here
>>> end
>>>
>>> I could see this as being handy
>>
>> What's wrong with
>>
>> def inc
>> incrementing_logic_goes_here
>> end
>>
>> How is that any different?
>>
>
> What's wrong with Array#push? Why do we need Array#<<? How is that any
> different?

irb(main):001:0> [].push(1,2,3)
=> [1, 2, 3]
irb(main):002:0> [].<<(1,2,3)
ArgumentError: wrong number of arguments (3 for 1)

:-) But I know that's not what you meant. The thing is, a method
called ++ that did in-place incremention would not be meaningful for
numbers (if I understand correctly that you mean it would be similar
to succ!), and having it for other objects would probably just lead to
more confusion. That's my hunch, at least.

Rick DeNatale

unread,
Nov 5, 2009, 8:50:03 PM11/5/09
to
On Wed, Nov 4, 2009 at 11:55 AM, Seebs <usenet...@seebs.net> wrote:

> On 2009-11-04, Yukihiro Matsumoto <ma...@ruby-lang.org> wrote:
>> In message "Re: Ruby doesn't implement x++ for Fixnum's because ???"
>>     on Wed, 4 Nov 2009 23:31:46 +0900, Marnen Laibow-Koser <mar...@marnen.org> writes:
>
>>|I believe you are quite wrong.  If a destructive function like gsub! can
>>|be implemented as a method, then I see no reason that +=, |=, or postfix
>>|++ couldn't be.
>
>> Only if you accept the language that can change the value of 1 to 2.
>> I don't.
>
> Hmph.  Fortran can change constants, why's Ruby so much less powerful?

But Fortran fixed that bug in its first revision!

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

Gavin Sinclair

unread,
Nov 6, 2009, 4:18:16 AM11/6/09
to
>
> What's wrong with Array#push?  Why do we need Array#<<?  How is that any
> different?

Apart from David's response, you're proposing that a currently-invalid
method name be allowed. For such a change, there needs to be a good
reason.

Gavin

Tony Arcieri

unread,
Nov 6, 2009, 2:17:52 PM11/6/09
to
[Note: parts of this message were removed to make it a legal post.]

On Thu, Nov 5, 2009 at 5:28 PM, David A. Black <dbl...@rubypal.com> wrote:

> The thing is, a method called ++ that did in-place incremention would not
> be meaningful for
> numbers (if I understand correctly that you mean it would be similar
> to succ!), and having it for other objects would probably just lead to
> more confusion. That's my hunch, at least.


There's no point at all if it doesn't work on numbers.

It would require special case behavior. Application to literal numbers
would be strange. But there's certainly no reason it can't be done, and you
have one Ruby implementer on this thread attesting that it can.

--
Tony Arcieri
Medioh/Nagravision

David A. Black

unread,
Nov 6, 2009, 2:41:05 PM11/6/09
to
Hi --

On Sat, 7 Nov 2009, Tony Arcieri wrote:

> On Thu, Nov 5, 2009 at 5:28 PM, David A. Black <dbl...@rubypal.com> wrote:
>
>> The thing is, a method called ++ that did in-place incremention would not
>> be meaningful for
>> numbers (if I understand correctly that you mean it would be similar
>> to succ!), and having it for other objects would probably just lead to
>> more confusion. That's my hunch, at least.
>
>
> There's no point at all if it doesn't work on numbers.

It depends how you define "work" :-) I'll stick with my formulation,
though: in-place incrementation of a numeric is not meaningful. So if
++ is understood to be in-place incrementation (like succ!), which is
how I interpreted your earlier post, then it wouldn't be meaningful
for numbers.

> It would require special case behavior. Application to literal numbers
> would be strange. But there's certainly no reason it can't be done, and you
> have one Ruby implementer on this thread attesting that it can.

It seems like a lot of special-casing and strangeness, though. I'm a
little bit hampered in discussing it, I guess, because I don't see
what benefit it would confer in exchange for the anomaly. So I'm
probably going in circles.

Seebs

unread,
Nov 6, 2009, 3:38:39 PM11/6/09
to
On 2009-11-06, David A. Black <dbl...@rubypal.com> wrote:
> It seems like a lot of special-casing and strangeness, though. I'm a
> little bit hampered in discussing it, I guess, because I don't see
> what benefit it would confer in exchange for the anomaly. So I'm
> probably going in circles.

I have found a lot of idioms which are amenable to use with ++, especially
postincrement, but they are often not nearly so useful outside of the C-like
languages.

Consider the canonical inner loop for copying an array in C:
s[i++] = t[j++];

There's really no idiomatic equivalent -- nor a need for one, usually.

David A. Black

unread,
Nov 6, 2009, 3:49:32 PM11/6/09
to
Hi --

On Sat, 7 Nov 2009, Seebs wrote:

> On 2009-11-06, David A. Black <dbl...@rubypal.com> wrote:
>> It seems like a lot of special-casing and strangeness, though. I'm a
>> little bit hampered in discussing it, I guess, because I don't see
>> what benefit it would confer in exchange for the anomaly. So I'm
>> probably going in circles.
>
> I have found a lot of idioms which are amenable to use with ++, especially
> postincrement, but they are often not nearly so useful outside of the C-like
> languages.
>
> Consider the canonical inner loop for copying an array in C:
> s[i++] = t[j++];
>
> There's really no idiomatic equivalent -- nor a need for one, usually.

Oh, I have no problem with ++ per se. It just seems against the grain
in Ruby.

Michael W. Ryder

unread,
Nov 6, 2009, 4:24:03 PM11/6/09
to
Walton Hoops wrote:
>> -----Original Message-----
>> From: mar...@marnen.org [mailto:mar...@marnen.org]
>>>> Now consider the ruby way:
>>>>
>>>> 10.times do |i|
>>>> print "#{i},"
>>>> end
>>>>
>>>> Some length as the C code, but much more readable. Heck, it's
>>>> almost English!

But if you wanted to do something like:
i = 10;
while (i > 0)
{
printf("%d/n", i--);
}
in Ruby you would have to do something like:
i = 10
while (i > 0)
puts i
i -= 1
end
As far as I can tell there is no way in Ruby to use .each or .times to
go backwards. While I realize this thread is about the ++ operator the
-- operator is complementary.

<snip>

Marnen Laibow-Koser

unread,
Nov 6, 2009, 4:34:32 PM11/6/09
to
Michael W. Ryder wrote:
[...]
> But if you wanted to do something like:
> i = 10;
> while (i > 0)
> {
> printf("%d/n", i--);
> }
> in Ruby you would have to do something like:
> i = 10
> while (i > 0)
> puts i
> i -= 1
> end

No.

10.downto(1) do |i|
puts i
end

> As far as I can tell there is no way in Ruby to use .each or .times to
> go backwards.

That's what .downto is for. (Have you ever needed this? I have not.)

> While I realize this thread is about the ++ operator the
> -- operator is complementary.
>
> <snip>

Best,

Matthew K. Williams

unread,
Nov 6, 2009, 4:37:32 PM11/6/09
to

what about the downto method?

Matt

David A. Black

unread,
Nov 6, 2009, 4:41:53 PM11/6/09
to
Hi --

On Sat, 7 Nov 2009, Marnen Laibow-Koser wrote:

> Michael W. Ryder wrote:
> [...]
>> But if you wanted to do something like:
>> i = 10;
>> while (i > 0)
>> {
>> printf("%d/n", i--);
>> }
>> in Ruby you would have to do something like:
>> i = 10
>> while (i > 0)
>> puts i
>> i -= 1
>> end
>
> No.
>
> 10.downto(1) do |i|
> puts i
> end
>
>> As far as I can tell there is no way in Ruby to use .each or .times to
>> go backwards.
>
> That's what .downto is for. (Have you ever needed this? I have not.)

And in 1.9:

puts *10.downto(1)

and there's also #reverse_each.

Seebs

unread,
Nov 6, 2009, 6:25:16 PM11/6/09
to
On 2009-11-06, David A. Black <dbl...@rubypal.com> wrote:
> Oh, I have no problem with ++ per se. It just seems against the grain
> in Ruby.

Yeah. I think fundamentally it's the "variables aren't objects" thing.
++ is intended to operate on a specific object, and doesn't make sense
if "x = x + 1" doesn't really mean "modify the specific object x".

Michael W. Ryder

unread,
Nov 6, 2009, 6:47:56 PM11/6/09
to
Marnen Laibow-Koser wrote:
> Michael W. Ryder wrote:
> [...]
>> But if you wanted to do something like:
>> i = 10;
>> while (i > 0)
>> {
>> printf("%d/n", i--);
>> }
>> in Ruby you would have to do something like:
>> i = 10
>> while (i > 0)
>> puts i
>> i -= 1
>> end
>
> No.
>
> 10.downto(1) do |i|
> puts i
> end
>
>> As far as I can tell there is no way in Ruby to use .each or .times to
>> go backwards.
>
> That's what .downto is for. (Have you ever needed this? I have not.)
>

I missed the downto method, I guess that is a problem when you have so
many different ways to do the same basic things. I much prefer the
simplicity of Basic and C with for loops that can go either direction.
As far as going backwards I use it a lot to parse strings of the form
"city name ST 12345-6789" to City, State, and Zip Code fields. I look
for the first blank from the end of the string and assume everything
after it is the Zip Code, I then find the next two non-blank characters
and assign them to State, and everything else is the City name.

David A. Black

unread,
Nov 6, 2009, 7:41:17 PM11/6/09
to
Hi --

I think one thing that's getting lost in the sauce here is that Ruby
does have idioms like:

a -= 1

for bumping things up and down and other operations. So you can
maintain a manual index on a collection or string traversal easily if
you need to. I'd say that most of the time, though, you won't need to.

Marnen Laibow-Koser

unread,
Nov 6, 2009, 11:20:39 PM11/6/09
to
Michael W. Ryder wrote:
[...]
>. I much prefer the
> simplicity of Basic and C with for loops that can go either direction.

That's because you're trying to write C in Ruby. There are far more
idiomatic ways of doing things -- and they *are* clearer, at least in a
Ruby context.

> As far as going backwards I use it a lot to parse strings of the form
> "city name ST 12345-6789" to City, State, and Zip Code fields. I look
> for the first blank from the end of the string and assume everything
> after it is the Zip Code, I then find the next two non-blank characters
> and assign them to State, and everything else is the City name.

That's great in a language like C that doesn't have very good string
handling. The Ruby way to do this would be
city, state, zip = string.split(/\s+/)

No incrementing. No iteration. Just a clear declarative syntax.

Best,
--
Marnen Laibow-Koser
http://www.marnen.org
mar...@marnen.org

Walton Hoops

unread,
Nov 7, 2009, 12:54:45 AM11/7/09
to
> -----Original Message-----
> From: Michael W. Ryder [mailto:_mwry...@gmail.com]
> But if you wanted to do something like:
> i = 10;
> while (i > 0)
> {
> printf("%d/n", i--);
> }
> in Ruby you would have to do something like:
> i = 10
> while (i > 0)
> puts i
> i -= 1
> end
> As far as I can tell there is no way in Ruby to use .each or .times to
> go backwards. While I realize this thread is about the ++ operator the
> -- operator is complementary.

Others have mentioned reverse each and downto, so I'll just throw in one
more. If you are determined to save that line, you also have:
(untested, so if I'm off my one, from the C feel free to tar and feather me)

i=11
while (i-=1) > 0
puts i
end

or:

i=11;
while i > 0
puts (i-=1)
end

I also think this demonstrates my previous point, that playing Perl golf
serves no one. I've found it rare that saving a line at the cost of
readability improves code in any way. If the interpreter is any good,
your 5 line example should execute just as fast as my 4 line, and it's
certainly much clearer what is actually being done. I've seen plenty of
C programmers who really should know better, get confused by ++ in
unexpected places.


What it all comes down to in my personal opinion (as no one of any real note)
is that while ++ can be a cool little operator, it really doesn't give enough
benefit to be worth the confusion involved in implementing it in Ruby. It's
been made plenty clear by others why ++ would have to be a special case operator
in Ruby (as opposed to the other operators which are simple methods), but why
write special logic for this one silly operator that at BEST saves us one line
of code here and there?


David A. Black

unread,
Nov 7, 2009, 4:39:01 AM11/7/09
to
Hi --

On Sat, 7 Nov 2009, Marnen Laibow-Koser wrote:

> Michael W. Ryder wrote:
> [...]
>> . I much prefer the
>> simplicity of Basic and C with for loops that can go either direction.
>
> That's because you're trying to write C in Ruby. There are far more
> idiomatic ways of doing things -- and they *are* clearer, at least in a
> Ruby context.
>
>> As far as going backwards I use it a lot to parse strings of the form
>> "city name ST 12345-6789" to City, State, and Zip Code fields. I look
>> for the first blank from the end of the string and assume everything
>> after it is the Zip Code, I then find the next two non-blank characters
>> and assign them to State, and everything else is the City name.
>
> That's great in a language like C that doesn't have very good string
> handling. The Ruby way to do this would be
> city, state, zip = string.split(/\s+/)

You'd need to take multi-word city names into account, though. So
maybe:

city, state, zip = /\A(.*)\s+(\S+)\s+(\S+)\Z/.match(str).captures

Marnen Laibow-Koser

unread,
Nov 7, 2009, 10:02:41 AM11/7/09
to
David A. Black wrote:
> Hi --
>
> On Sat, 7 Nov 2009, Marnen Laibow-Koser wrote:
>
>>> "city name ST 12345-6789" to City, State, and Zip Code fields. I look
>>> for the first blank from the end of the string and assume everything
>>> after it is the Zip Code, I then find the next two non-blank characters
>>> and assign them to State, and everything else is the City name.
>>
>> That's great in a language like C that doesn't have very good string
>> handling. The Ruby way to do this would be
>> city, state, zip = string.split(/\s+/)
>
> You'd need to take multi-word city names into account, though. So
> maybe:
>
> city, state, zip = /\A(.*)\s+(\S+)\s+(\S+)\Z/.match(str).captures
>

Quite right. I was trying for simplicity, but that had indeed crossed
my mind.

>
> David
>
> --
> 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)

Best,

RichardOnRails

unread,
Nov 7, 2009, 6:08:45 PM11/7/09
to
On Nov 4, 4:59 pm, Yukihiro Matsumoto <m...@ruby-lang.org> wrote:
> Hi,

>
> In message "Re: Ruby doesn't implement x++ for Fixnum's because ???"
>     on Thu, 5 Nov 2009 04:25:05 +0900, RichardOnRails <RichardDummyMailbox58...@USComputerGurus.com> writes:
>
> |BTW,  I'm not advocating x++ for Ruby.  I'm just trying to understand
> |whether Ruby would literally change 1 to 2 as opposed to change a
> |variable that contains 1 to subsequently contain 2.
>
> There's no way to modify local variables by sending message in Ruby.
>
>                                                         matz.

Thanks for your response, Matz.
I've got to study David Black's book more thoroughly.

Best wishes,
Richard

Tony Arcieri

unread,
Nov 8, 2009, 11:48:51 AM11/8/09
to
[Note: parts of this message were removed to make it a legal post.]

On Fri, Nov 6, 2009 at 4:30 PM, Seebs <usenet...@seebs.net> wrote:

> "variables aren't objects"


I've seen this mentioned a few times. I think it's something of a gross
misstatement of a problem, and a deeper understanding might be able to peel
away some of the layers of the debate here.

I can't think of a language where "variables are objects". And this isn't
the issue. The real issue is Numeric values (i.e. "objects") are
immutable. Other types of objects, however, are mutable. "Everything is an
object", except some objects are different than others.

Advocates of allowing a ++ operator are suggesting that the operator have a
dispatch model which alters the local binding when applied to Numeric
types. I'm further suggesting it be dispatched like any other operator when
applied to non-numeric types.

What I really see happening here is that ++ reveals an otherwise
difficult-to-see difference in how immutable and mutable objects behave in
Ruby. There's no reason Ruby can't have ++, but it would need special case
behavior, because the behavior of Numerics is already a special case. Any
ugliness surrounding special-case behavior of ++ when implementing it
against Numerics stems from this inconsistency in Ruby itself, not the ++
operator.

It's not that I doubt the pragmatism of the immutability of Numeric values
(on the contrary, I'm developing a language where *all* values are
immutable), but this is really the cause of the problem, and the solution
(special casing how Numerics respond to ++ by providing alterations to the
local binding) causes me no qualms, as it's only a workaround of the
separation of immutable/mutable objects that's a fundamental part of Ruby to
begin with.

--
Tony Arcieri
Medioh/Nagravision

Rick DeNatale

unread,
Nov 8, 2009, 12:45:07 PM11/8/09
to
On Sun, Nov 8, 2009 at 11:48 AM, Tony Arcieri <to...@medioh.com> wrote:
> On Fri, Nov 6, 2009 at 4:30 PM, Seebs <usenet...@seebs.net> wrote:
>
>> "variables aren't objects"
>
>
> I've seen this mentioned a few times.  I think it's something of a gross
> misstatement of a problem, and a deeper understanding might be able to peel
> away some of the layers of the debate here.
>
> I can't think of a language where "variables are objects".  And this isn't
> the issue.

In C++ a variable can actually hold the state of an object rather than
simply a reference to the object.

If you think of object as simply meaning what holds the state of what
is denoted by a variable, then C variables hold objects, and since a
pointer represents state, even pointer's can be considered objects in
this degenerate (if you will) form.

And that really is the point with the ++ operator, at least if you
want it to have the semantics of C/C++.

the c/c++ expression

b = a++

has the meaning.

1) copy the current contents of the a variable to b
2) increment the contents of the variable a according to the static
type of a, e.g. if it's an int or a pointer to a char add 1 to it, if
it's a pointer to a (4-byte) int add 4 to it, etc.

The original quest in this thread was to do this by defining a ++
method for FixNum (or Integer).

As Matz himself has pointed out in this thread,

>
> There's no way to modify local variables by sending message in Ruby.
>
> matz.

Which is something I've said on this thread before (multiple times IIRC).

This has nothing to do with whether or not the object bound to a
variable is immutable, it has to do with how ruby variable bindings
can and cannot be changed, and that is the whole point.

Now, while it's true that Fixnums have a property of being represented
by an immediate value rather than a pointer to a 'boxed' value, and
this is possible because they are immutable, it doesn't mean that
local variables with non-immediate bindings can be rebound inside the
invocation of another method.

The only way to define b = a++. in Ruby with C/C++ semantics would be
to alter the parser to treat such expressions as syntactic sugar,
(which was Charle's proposal), much like += is handled now.

Let's say this were done, perhaps by the parser treating:

b = a++

as if it were

b, a = a, a.succ

much like it treats

a += 1

as if it were

a = a + 1

The actual parser changes would need to be sensitive to other cases like

foo(b + a++)

which would need to compute a + b before incrementing a.

One could alter what the increment did, by redefining succ or a
particular class, much like redefining + for a given class can alter
the value of a + 1 for a particular binding of a.

But one could still not move the actual change of binding into a
method, any more than you can redefine the '=' part of '+='

Seebs

unread,
Nov 8, 2009, 1:01:27 PM11/8/09
to
On 2009-11-08, Tony Arcieri <to...@medioh.com> wrote:
> I can't think of a language where "variables are objects".

I'd say they are in C.

In C:
{
int x;
}

x is an object. There is storage which is reserved for x, which is not
associated with any other object, etcetera. Modifications "to x" always
affect this specific object; you can't make x be some other object, all
you can do is change its contents.

> And this isn't
> the issue. The real issue is Numeric values (i.e. "objects") are
> immutable. Other types of objects, however, are mutable. "Everything is an
> object", except some objects are different than others.

I think it is the issue though.

The reason you can write "x = x + 1" in Ruby, but not "x++", is that you
have to modify the variable, not the object. If x was previously the Fixnum
1, you don't want to change 1 to 2 -- you want to change x to point to a
different object. You can't do that by sending x a message, though, you
have to write it in the code that knows about the variable x.

> Advocates of allowing a ++ operator are suggesting that the operator have a
> dispatch model which alters the local binding when applied to Numeric
> types.

(1+2)++

1+2 => the Fixnum 3

What is the local binding which gets incremented? There's no variable there,
only an object.

> What I really see happening here is that ++ reveals an otherwise
> difficult-to-see difference in how immutable and mutable objects behave in
> Ruby. There's no reason Ruby can't have ++, but it would need special case
> behavior, because the behavior of Numerics is already a special case. Any
> ugliness surrounding special-case behavior of ++ when implementing it
> against Numerics stems from this inconsistency in Ruby itself, not the ++
> operator.

I don't entirely agree. The difference is most *obvious* with Numerics,
but it's true of just about anything.

Imagine that we define ++ on an array as equivalent to "a = a + [ nil ]".
That is, it appends a new value on the end of the array.

Now try setting up an array:
a = Array.new
b = a
a++

How many items does b have? Why, it now has an item, because there is only
one array. a and b are not arrays; a and b are variables which hold
references to a single array object.

What that means is that, while Numerics have special case behavior, *the
special case behavior is the one we actually want*.

Ignore the return value for a moment. Clearly, the *intent* of "a++" is
the same as the *intent* of "a = a + 1". But in Ruby, those aren't the
same thing.

a = Array.new
b = a
a = a + [ nil ]

This makes a and b into two separate objects.

> It's not that I doubt the pragmatism of the immutability of Numeric values
> (on the contrary, I'm developing a language where *all* values are
> immutable), but this is really the cause of the problem, and the solution
> (special casing how Numerics respond to ++ by providing alterations to the
> local binding) causes me no qualms, as it's only a workaround of the
> separation of immutable/mutable objects that's a fundamental part of Ruby to
> begin with.

I disagree, because I think it would violate POLS to have ++ work differently
on numerics, when clearly, that behavior (alters local binding) is exactly
what we want... Probably.

Again, I really think the root of this is that ++ is designed for a language
in which the variable is its own object, not a reference to another object.

Seebs

unread,
Nov 8, 2009, 1:06:47 PM11/8/09
to
On 2009-11-08, Rick DeNatale <rick.d...@gmail.com> wrote:
> If you think of object as simply meaning what holds the state of what
> is denoted by a variable, then C variables hold objects, and since a
> pointer represents state, even pointer's can be considered objects in
> this degenerate (if you will) form.

Insofar as anything in C is "an object", pointers are.

Tony Arcieri

unread,
Nov 8, 2009, 1:18:54 PM11/8/09
to
[Note: parts of this message were removed to make it a legal post.]

On Sun, Nov 8, 2009 at 10:45 AM, Rick DeNatale <rick.d...@gmail.com>wrote:

> As Matz himself has pointed out in this thread,
>
> >
> > There's no way to modify local variables by sending message in Ruby.
> >
> > matz.
>
> Which is something I've said on this thread before (multiple times IIRC).
>
> This has nothing to do with whether or not the object bound to a
> variable is immutable, it has to do with how ruby variable bindings
> can and cannot be changed, and that is the whole point.
>

You still seem to be missing what I'm proposing.

For Numerics, ++ would rebind. For everything else, it would be dispatched
as a message.

Am I being unclear?

--
Tony Arcieri
Medioh/Nagravision

Marnen Laibow-Koser

unread,
Nov 8, 2009, 1:22:47 PM11/8/09
to
Tony Arcieri wrote:
> On Sun, Nov 8, 2009 at 10:45 AM, Rick DeNatale
> <rick.d...@gmail.com>wrote:
>
>> variable is immutable, it has to do with how ruby variable bindings
>> can and cannot be changed, and that is the whole point.
>>
>
> You still seem to be missing what I'm proposing.
>
> For Numerics, ++ would rebind. For everything else, it would be
> dispatched
> as a message.

Yuuuuuuuck! Why do this ugly special-casing for something that's hardly
ever needed anyway?
>
> Am I being unclear?

No, just silly. :D

Tony Arcieri

unread,
Nov 8, 2009, 1:25:22 PM11/8/09
to
[Note: parts of this message were removed to make it a legal post.]

On Sun, Nov 8, 2009 at 11:22 AM, Marnen Laibow-Koser <mar...@marnen.org>wrote:

> Yuuuuuuuck! Why do this ugly special-casing for something that's hardly
> ever needed anyway?
>

To reiterate from my previous message, because the behavior of Numerics is
already a special case to begin with.

--
Tony Arcieri
Medioh/Nagravision

Walton Hoops

unread,
Nov 8, 2009, 1:49:46 PM11/8/09
to
> -----Original Message-----
> From: bas...@gmail.com [mailto:bas...@gmail.com] On Behalf Of Tony
> To reiterate from my previous message, because the behavior of Numerics
> is already a special case to begin with.

How? Because they are immutable? That's not special casing, that's just
how the class is designed. I can write an immutable class in Ruby,
without any special casing.


Rick DeNatale

unread,
Nov 8, 2009, 1:50:33 PM11/8/09
to

Tony Arcieri

unread,
Nov 8, 2009, 2:13:33 PM11/8/09
to
[Note: parts of this message were removed to make it a legal post.]

On Sun, Nov 8, 2009 at 11:50 AM, Rick DeNatale <rick.d...@gmail.com>wrote:

> No, but you ARE missing the fact that the lack of being able to rebind
> a variable via a method has NOTHING to do with the class of the object
> which is currently bound to that variable.
>

But the rebinding is being done by an operator, not a method, and there's
ample precedent for operators that perform rebinding in Ruby (=, +=, -=, /=,
etc)

--
Tony Arcieri
Medioh/Nagravision

Seebs

unread,
Nov 8, 2009, 2:13:24 PM11/8/09
to
On 2009-11-08, Tony Arcieri <to...@medioh.com> wrote:
> You still seem to be missing what I'm proposing.

> For Numerics, ++ would rebind. For everything else, it would be dispatched
> as a message.

> Am I being unclear?

I don't think that gives the right semantics in many cases. It's also
not clear that rebinding works:

array_example.length++

What should this do?

Seebs

unread,
Nov 8, 2009, 2:14:22 PM11/8/09
to
On 2009-11-08, Tony Arcieri <to...@medioh.com> wrote:
> But the rebinding is being done by an operator, not a method, and there's
> ample precedent for operators that perform rebinding in Ruby (=, +=, -=, /=,
> etc)

And which of those operators special-case Numeric?

Any of them? I don't think so.

If it's to be a rebinding operator, it ought to rebind for everything, not
just for numerics.

Tony Arcieri

unread,
Nov 8, 2009, 2:16:59 PM11/8/09
to
[Note: parts of this message were removed to make it a legal post.]

On Sun, Nov 8, 2009 at 11:49 AM, Walton Hoops <wal...@vyper.hopto.org>wrote:

> How? Because they are immutable? That's not special casing, that's just
> how the class is designed. I can write an immutable class in Ruby,
> without any special casing.
>

Yes, non-Numeric objects can be immutable. However, Numeric objects can't
be mutable.

--
Tony Arcieri
Medioh/Nagravision

Tony Arcieri

unread,
Nov 8, 2009, 2:32:25 PM11/8/09
to
[Note: parts of this message were removed to make it a legal post.]

On Sun, Nov 8, 2009 at 12:20 PM, Seebs <usenet...@seebs.net> wrote:

> I don't think that gives the right semantics in many cases. It's also
> not clear that rebinding works:
>
> array_example.length++
>
> What should this do?
>

Well, this is a very interesting question, as I discovered something about
Ruby I didn't know from this...

Say we have:

class Foo
attr_reader :bar

def initialize
@bar = 0
end
end

f = Foo.new
f.bar += 1

What do you think the value of a subsequent call to f.bar will be?

I was surprised to discover that it indeed 1. Somehow += is mutating the
ivar through a supposed "attr_reader" even though there is no corresponding
bar= method. In that case += appears to be frobbing the ivar directly.

Very strange. Even worse:

class Foo
def initialize
@bar = 0
end

def bar
@bar + 1
end
end

f = Foo.new
f.bar += 1

Now what do you think the value of a subsequent call to f.bar will be?

Indeed, it would be 3!

I cannot begin to answer this question because Ruby is doing strange and
unexpected things here, at least from my perspective...

--
Tony Arcieri
Medioh/Nagravision

Tony Arcieri

unread,
Nov 8, 2009, 2:37:06 PM11/8/09
to
[Note: parts of this message were removed to make it a legal post.]

On Sun, Nov 8, 2009 at 12:32 PM, Tony Arcieri <to...@medioh.com> wrote:

> I cannot begin to answer this question because Ruby is doing strange and
> unexpected things here, at least from my perspective...
>

Never mind, bar= was still defined because I was reopening the class.

So to answer your question:

array_example.length++

..would attempt to rebind through #length=, and fail if it weren't defined.

--
Tony Arcieri
Medioh/Nagravision

Tony Arcieri

unread,
Nov 8, 2009, 2:43:05 PM11/8/09
to
[Note: parts of this message were removed to make it a legal post.]

On Sun, Nov 8, 2009 at 12:20 PM, Seebs <usenet...@seebs.net> wrote:

> And which of those operators special-case Numeric?
>
> Any of them? I don't think so.
>

Admittedly it would be a first.


> If it's to be a rebinding operator, it ought to rebind for everything, not
> just for numerics.


To borrow a phrase from 37signals, "context is more important than
consistency"

--
Tony Arcieri
Medioh/Nagravision

Walton Hoops

unread,
Nov 8, 2009, 3:15:44 PM11/8/09
to
> From: bas...@gmail.com [mailto:bas...@gmail.com] On Behalf Of Tony
> Yes, non-Numeric objects can be immutable. However, Numeric objects
> can't
> be mutable.

Incorrect. In fact the very first message in this thread provided an
example of redifining Fixnum in such a way that it was mutable.


It is loading more messages.
0 new messages