Why no ++ and --?

  • Thread starter Sonja Elen Kisa
  • Start date
S

Sonja Elen Kisa

"foo += 1" somehow seems less elegant or pretty as "foo++".

Is there any reason Ruby doesn't have ++? Is it something that might be
added in a future version?
 
T

Tony Arcieri

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

"foo += 1" somehow seems less elegant or pretty as "foo++".

Is there any reason Ruby doesn't have ++? Is it something that might be
added in a future version?

I think this is something of a dead horse around here. The short answer is:
matz doesn't want it, most rubyists don't want it (and even actively oppose
it), therefore it's never going to happen. Adding ++ would break backwards
compatibility with libraries like superators:
http://jicksta.com/posts/superators-add-new-operators-to-ruby

However, there's no technical reason why Ruby can't have a x++ operator
which functions as shorthand for:

begin; _tmp = x; x += 1; _tmp; end
 
S

Seebs

"foo += 1" somehow seems less elegant or pretty as "foo++".
Is there any reason Ruby doesn't have ++?
Yes.

Is it something that might be
added in a future version?

Very unlikely.

In Ruby, "foo" is not an object, it's a reference to an object. Not all
objects are mutable. After:

foo = 3

"foo" is just a name to refer to the Fixnum 3. That object CANNOT be
modified. When you write:
foo = foo + 1
what happens is:
We extract the current value of foo (fixnum 3).
We send that an add message with the other argument being the fixnum 1
That yields a new object, the fixnum 4
Foo is changed to be a reference to that new object

You can't increment the underlying object, because fixnums are immutable.

-s
 
A

Aldric Giacomoni

Seebs said:

You know, I really thought the Ruby Way (tm) embraced, nay, espoused
DRY. I'm going to reference the earlier post.. Which referenced an
earlier thread..
http://blade.nagaokaut.ac.jp/cgi-bi...talk/349253?349080-351096+split-mode-vertical

There's -nothing- which needs to be said which hasn't been said in that
other thread.

I call this thread dead and buried, right on top of the dead horse which
has been flogged one too many times, and just to make sure no one
touches it again, I'll put the word 'nazi' and call Godwin's law on
myself.
 
T

Tony Arcieri

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

You can't increment the underlying object, because fixnums are immutable.

Not to beat the dead horse any more but...

In a language like Ruby where the binding operates entirely by reference, it
would only make sense for the ++ operator to change which object a variable
name references (i.e. destructive assignment) as opposed to sending a
message which actually mutates the object it references, especially since ++
is an operator intended to work with numbers and Ruby's numbers are
immutable.

Using x++ as a shorthand for:

begin; _tmp = x; x += 1; _tmp; end

...would be the only sensible implementation.

There exists an operator in Ruby which doesn't send a message: =. The "="
operator modifies the binding. ++ (and --) would have to do the same.

Unprecedented? Yes. But not impossible.
 
M

Marnen Laibow-Koser

Aldric said:
You know, I really thought the Ruby Way (tm) embraced, nay, espoused
DRY. I'm going to reference the earlier post.. Which referenced an
earlier thread..
http://blade.nagaokaut.ac.jp/cgi-bi...talk/349253?349080-351096+split-mode-vertical

There's -nothing- which needs to be said which hasn't been said in that
other thread.

I call this thread dead and buried, right on top of the dead horse which
has been flogged one too many times, and just to make sure no one
touches it again, I'll put the word 'nazi' and call Godwin's law on
myself.

...which doesn't work when intentionally invoked. What are you, some
kind of operator-Nazi? :)

Best,
-- 
Marnen Laibow-Koser
http://www.marnen.org
(e-mail address removed)
 
R

Rob Biedenharn

Not to beat the dead horse any more but...

In a language like Ruby where the binding operates entirely by
reference, it
would only make sense for the ++ operator to change which object a
variable
name references (i.e. destructive assignment) as opposed to sending a
message which actually mutates the object it references, especially
since ++
is an operator intended to work with numbers and Ruby's numbers are
immutable.

Using x++ as a shorthand for:

begin; _tmp = x; x += 1; _tmp; end

...would be the only sensible implementation.

There exists an operator in Ruby which doesn't send a message: =.
The "="
operator modifies the binding. ++ (and --) would have to do the same.

Unprecedented? Yes. But not impossible.


Well, I could see a sensible implementation equivalent to:

begin; _tmp = x; x = x.succ; _tmp; end

or perhaps

begin; _tmp = x; x.succ!; _tmp; end

so that's certainly not the "only" sensible implementation :)

-Rob

P.S. Sorry from flailing the horse.

Rob Biedenharn http://agileconsultingllc.com
(e-mail address removed)
 
T

Tony Arcieri

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

begin; _tmp = x; x.succ!; _tmp; end

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

Good luck implementing that one.

There doesn't seem to be much left of this dead horse's flesh.
 
C

Christopher Dicely

"foo += 1" somehow seems less elegant or pretty as "foo++".

"foo += 1" doesn't have the same meaning as "foo++", instead, it is
equivalent to "++foo".
"foo++" is (as others have intimated in suggesting implementations)
equivalent to:
begin
_temp = foo
foo += 1
_temp
end

I wouldn't expect to see postfix-increment/decrement operators added
to Ruby in any near-future version.
 
J

Josh Cheek

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

They just plain don't mean the same thing:

In C++, outputs "ref1 = 6 , ref2 = 6" Because ++ changes the underlying
object, and they both referencing that object.
#include "iostream"
int main( ) {
int actual=5 , &ref1=actual , &ref2=ref1;
++ref1;
std::cout << "ref1 = " << ref1 << ", ref2 = " << ref2 << std::endl;
return 0;
}

In C, outputs "*ptr1 = 6 , *ptr2 = 6" For the same reason as above, We
increment the value that ptr1 is pointing at, since ptr2 is pointing to the
same place, it gets updated also
#include "stdio.h"
int main(){
int actual=5 , *ptr1=&actual , *ptr2=ptr1;
++*ptr1;
printf( "*ptr1 = %d , *ptr2 = %d\n" , *ptr1 , *ptr2 );
return 0;
}

In Ruby, outputs "ref1 = 6 , ref2 = 5" Because += creates a new object, and
updates one of the references to point to the new place in memory, but the
second reference is still pointing to the old number.
actual=5 ; ref1=actual ; ref2=ref1
ref1 += 1
puts "ref1 = #{ref1} , ref2 = #{ref2}"


Numbers are immutable in Ruby, so you cannot increment a number that the
object represents, you can only get a new object containing the next number.
And anything referring to the original number will not be updated, that
original number still exists. So where do you compromise? Does ref1++
translate directly to ref1+=1 which would give it very different meaning
than in the languages the people making the requests are coming from, or do
you make numbers mutable, which would present other issues that these people
would dislike (ie making numbers immutable allows them to mimic the
behaviour of pass by value, but now they would either have to explicitly
duplicate the number before passing it, or they would have to deal with the
possibility of the function they are calling having the ability to change
it, or some sort of magic such as checking params and duping them before
letting them in)

I think that people who ask for ++ really don't understand what they are
asking for, and think it is just a simple syntactic difference. I also think
you can trash a beautiful language by giving in to every half-understood
request for exceptional changes, so I'm very much against adding this, my
brain can only remember so many exceptions to the rules.
 
J

Josh Cheek

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

I thought it might be interesting to see how Java handles this, since it has
both primitives and wrappers.

Outputs
primative1 = 6 , primative2 = 5
immutable1 = 6, immutable2 = 5
mutable1 = 4, mutable2 = 4



public class IntWrapper {
public static void main(String[] args) {
// Java does not support references to primitive types, so primative2 =
primative1 creates a new int
// with the same value as primative1. Then when we incrememnt
primative1, primative2's value does not change
int primative1 = 5;
int primative2 = primative1;
primative1++;
System.out.println( "primative1 = " + primative1 + " , primative2 = " +
primative2 );

// because Integer is immutable, immutable1 and immutable2 end up
pointing to different objects
// and they have different values. This contradicts the C / C++ model,
as well as the general object model
Integer immutable1 = new Integer(5);
Integer immutable2 = immutable1;
immutable1++;
System.out.println( "immutable1 = " + immutable1 + ", immutable2 = " +
immutable2 );

// an example of how mutable objects behave, that shows the difference,
in this case,
// the object is mutable, so mutable1 and mutable2 both point to the
same object
// and when it is updated, they both reflect this change
// using a method .increment() because java does not support operator
overloading.
IntWrapper mutable1 = new IntWrapper(3);
IntWrapper mutable2 = mutable1;
mutable1.increment();
System.out.println( "mutable1 = " + mutable1 + ", mutable2 = " +
mutable2 );
}

public int num;
public IntWrapper( int num ) { this.num = num; }
public void increment() { num++; }
public String toString() { return Integer.toString(num); }
}


Ruby avoids the criticism of contradicting the C/C++ model, and general
object model because it's immutable classes don't implement self-modifying
methods like ++, every method returns a new object.
 
T

Tony Arcieri

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

I think that people who ask for ++ really don't understand what they are
asking for, and think it is just a simple syntactic difference.

Sorry to flay the dead horse's sun-bleached bones a bit more, but...

++ and -- (both prefix and postfix), were they to be added to Ruby, should
be implemented as little more than syntactic sugar. Much of the opposition
to ++ and -- comes from the idea that they *must* be implemented as methods
instead of as syntactic sugar as I've related previously in this post. It's
certainly internally consistent to implement all operators as methods, and
that's great, but Ruby doesn't implement "=" (or any assignment operators
like +=, *= etc) as a method.

Certain combinations of operations like obj[x] += 1 may involve complex
sequence of message dispatches. This operation sends the [] message to obj
with x as a parameter, then invokes the "+" method on the result of obj[x],
then invokes the []= method on obj with x and the result of the + operation.

So, not to toss any lighter fluid onto the horse's bleached bones, but I
think those opposed to "++" and "--" operators possess an intermediate
understanding of Ruby and don't know that down there in the trenches of Ruby
implementation, things are already a bit ugly. A single operator alone may
invoke multiple methods, and combinations thereof may permute that further,
particularly when assignment is involved. Operators ARE NOT directly
equivalent to method calls in all cases.

In a language like Ruby, if you were to introduce "++" and "--" they MUST be
classed as assignment operators; otherwise they don't make sense. Much of
the opposition to them seems to center around the "what if ++ and -- aren't
assignment operators?" argument which is certainly a dead horse. I freely
admit that trying to implement ++ or -- as anything but compound assignment
operators doesn't make any sense whatsoever.

Implementing these operators as syntactic sugar for something like this for
x++:

begin; _tmp = x; x += 1; _tmp; end

...is the only sensible solution, and anything else is a red herring.
 
L

Lui Kore

Just think about "a ++ -- - ++ -- b".
It doesn't save typing, you have to type more brakets usually !

"Yo dawg, I herd yo like ++s.
So I put a ++ in your ++ so you can ++ while you ++ "
 
L

lith

++ and -- (both prefix and postfix), were they to be added to Ruby, should
be implemented as little more than syntactic sugar.

I find that issue interesting in a slightly different perspective.
Shouldn't it be possible to implement that operator right in ruby and
doesn't it point to a shortcoming that there is no way to implement it
(other than using a decorator).
 
L

Lui Kore

I don't think there is any problem in implementation, but choosing a
subset of useful features is more important. Any language that want to
have every feature will surely fail, think about D.

I wish ++ can be added as a binary operator like it is in Haskell, not
the self-increamental one.
 
M

Marnen Laibow-Koser

lith said:
I find that issue interesting in a slightly different perspective.
Shouldn't it be possible to implement that operator right in ruby and
doesn't it point to a shortcoming that there is no way to implement it
(other than using a decorator).

No. The mechanics of assignment in Ruby are such that ++ is simply not
compatible with the structure of the language. It belongs to a
different programming paradigm.

Best,
 
T

Tony Arcieri

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

I find that issue interesting in a slightly different perspective.
Shouldn't it be possible to implement that operator right in ruby and
doesn't it point to a shortcoming that there is no way to implement it
(other than using a decorator).

++ and -- modify their receivers. Since Ruby's Numeric types are immutable,
they cannot be modified. So the only solution is to implement ++ and -- as
assignment operators.

Immutability certainly isn't a shortcoming, in fact it's very much a good
thing, especially when concurrency is involved. My own pet programming
language has no mutable state whatsoever and implements all operators that
modify their receivers as assignments.
 
L

lith

++ and -- modify their receivers. =A0Since Ruby's Numeric types are immut=
able,
they cannot be modified. =A0So the only solution is to implement ++ and -= - as
assignment operators.

Other languages solve similar problems by providing references/
pointers to variable or with macros etc. This isn't about
immutability.
 
S

Seebs

I find that issue interesting in a slightly different perspective.
Shouldn't it be possible to implement that operator right in ruby and
doesn't it point to a shortcoming that there is no way to implement it
(other than using a decorator).

I don't think so, no more than it points to a shortcoming of Ruby that
you can't implement = as an operator.

-s
 
S

Seebs

Other languages solve similar problems by providing references/
pointers to variable or with macros etc.

I don't think allowing references or pointers to variables would be good.
Variables are not objects, they're references already.
This isn't about immutability.

In practice it is, because when people say "x++", they don't want the variable
x to refer to a new object, they want the object x refers to increased.

-s
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,159
Messages
2,570,881
Members
47,418
Latest member
NoellaXku

Latest Threads

Top