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

G

Gavin Sinclair

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
 
T

Tony Arcieri

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

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

David A. Black

Hi --

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.


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

Seebs

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.

-s
 
D

David A. Black

Hi --

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.


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

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

Marnen Laibow-Koser

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

Matthew K. Williams

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!

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.

what about the downto method?

Matt
 
D

David A. Black

Hi --

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.


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

Seebs

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

-s
 
M

Michael W. Ryder

Marnen said:
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.
 
D

David A. Black

Hi --

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

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.


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

Marnen Laibow-Koser

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

Walton Hoops

-----Original Message-----
From: Michael W. Ryder [mailto:[email protected]]
But if you wanted to do something like:
i =3D 10;
while (i > 0)
{
printf("%d/n", i--);
}
in Ruby you would have to do something like:
i =3D 10
while (i > 0)
puts i
i -=3D 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=3D11
while (i-=3D1) > 0
puts i
end

or:

i=3D11;
while i > 0
puts (i-=3D1)
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=20
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?
 
D

David A. Black

Hi --

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


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

Marnen Laibow-Koser

David said:
Hi --



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

Tony Arcieri

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

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

Rick DeNatale

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

I can't think of a language where "variables are objects". =A0And this is= n'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 =3D 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 =3D 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 +=3D is handled now.

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

b =3D a++

as if it were

b, a =3D a, a.succ

much like it treats

a +=3D 1

as if it were

a =3D 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 '=3D' part of '+=3D'

--=20
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
 
S

Seebs

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.

-s
 
S

Seebs

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.

-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
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top