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

M

Michael W. Ryder

Walton said:
-----Original Message-----
From: (e-mail address removed) [mailto:[email protected]] 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!
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++.
 
R

RichardOnRails

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.


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


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


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

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
 
S

Seebs

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
 
T

Tony Arcieri

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

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

Marnen Laibow-Koser

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

Tony Arcieri

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

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

Marnen Laibow-Koser

Tony said:
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.

Best,
 
W

Walton Hoops

-----Original Message-----
From: Michael W. Ryder [mailto:[email protected]]
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.
 
T

Tony Arcieri

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

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

You can think of it like:

alias_method :++, :increment!
 
M

Michael W. Ryder

Walton Hoops wrote:
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.

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

Marnen Laibow-Koser

Michael said:
Walton Hoops 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

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.

Best,
 
W

Walton Hoops

-----Original Message-----
From: (e-mail address removed) [mailto:[email protected]]=20
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
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=20
'i' from 1 to 9 print 'i' followed by a comma. Sure, the words may not =
be=20
in the precise order, but it comes a darn site closer to natural =
language than:

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

Michael W. Ryder

Walton said:
-----Original Message-----
From: (e-mail address removed) [mailto:[email protected]]
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.
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.
 
G

Gavin Sinclair

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

Gavin Sinclair

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

Tobias Cohen

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

Aldric Giacomoni

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

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

Tony Arcieri

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

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

David A. Black

Hi--

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.


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)
 

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
473,773
Messages
2,569,594
Members
45,113
Latest member
Vinay KumarNevatia
Top