Things That Newcomers to Ruby Should Know (11/24/02)

The difference is that 3 is an immediate value object. There is only
ever one object with the value 3.

When I do:
a = 3
I am aliasing (referencing) 3; I am not setting an object to have
the immediate value 3.

Thus, if I were to do a.succ!, it would be no different than if I
were doing 3.succ!, because of the immediacy of Fixnum values and
the fact that variables are ONLY references to objects, and not
objects themselves.

(To be honest, I haven’t missed ++ because I’ve been working in
PL/SQL and Pascal recently.)

-austin
– Austin Ziegler, austin@halostatue.ca on 2002.11.25 at 23.33.34

···

On Tue, 26 Nov 2002 13:15:31 +0900, Jason Persampieri wrote:

You’re not changing the letter ‘a’ itself; you’re changing a
string which has the letter ‘a’ in it.

To put it another way:

You can have more than one “a” string:
s = “a”
t = “a”
and if you change or increment s:
s.succ! # s is now “b”
t doesn’t change.

But there’s only one of each number. If you were allowed to do
3.succ!
or
3 += 1
then when you did this:
puts 3 * 5
the output would be “20”, because you would have incremented the
actual object 3.
So wouldn’t it make send to have a somewhat global …succ! method
and only allow the programmer to increment (++) on those that have
it?

I mean, C doesn’t allow 3++ either (well, it may ALLOW it, but it
doesn’t mean anything). I think that argument is pretty bogus.

Think of it in terms of levels of indirection. A variable is just a
reference to an object, and methods called on a variable are actually
message sends to the object it references.

Now, in the case of a non-immediate value, we have

[Var]---->[Object]---->[Data]

so that, say, a = String.new(“Hello World”) is

[a]—>[String ]—>[Hello World]

and modifying ‘a’ modifies the data in the String object, not the
string object itself.

For immediate values, there is no intermediate per-instance object; all
Fixnums point to the same [3]. So a = 3; b=3; means

[a]–
±>[3]
[b]–/

Therefore there’s no real way to define a succ! on numbers, unless you
want to go the Java route and have int vs Int. And other than numbers
and iterators, I don’t think I’ve ever had the need to ++ something in
C++. I’d be a lot more annoyed if ruby had a ++ that didn’t work on
numbers than if it just didn’t have one.

Possibly illustrative:

a = 3; b = 3
puts a.id, b.id #=> 7, 7

c = “Hello World”; d = “Hello World”
puts c.id, d.id #=> 19659500 19659392

e = [c]; f = [c]
puts e.id, f.id #=> 19659128 19659008

c.succ!
p c,d,e,f #=> “Hello Worle” “Hello World” [“Hello Worle”] [“Hello Worle”]

martin

···

Jason Persampieri helgaorg@yahoo.com wrote:

So wouldn’t it make send to have a somewhat global
succ! method and only allow the programmer to
increment (++) on those that have it?

I mean, C doesn’t allow 3++ either (well, it may ALLOW
it, but it doesn’t mean anything). I think that
argument is pretty bogus.

It’s not bogus at all. It’s just a simpler
way of illustrating the fact that Ruby
operators operate on objects, not variables.

This is the same argument, using a variable
instead of a constant.

x = 3
y = 3
x++
puts y # 4???

Hal

···

----- Original Message -----
From: “Jason Persampieri” helgaorg@yahoo.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, November 25, 2002 10:15 PM
Subject: Re: Things That Newcomers to Ruby Should Know (11/24/02)

I mean, C doesn’t allow 3++ either (well, it may ALLOW
it, but it doesn’t mean anything). I think that
argument is pretty bogus.

Hi –

“Gavin Sinclair” gsinclair@soyabean.com.au writes:

Confusing implementation limitations and language design was Perl 5’s big
problem. Don’t let it become Ruby’s big problem too.

The above code merely demonstrates that String#chomp! doesn’t modify ‘self’,
rather it modifies the data of the object.

What I’m saying is that proof-by-current-implementation isn’t a great way
to argue the presence or absence of a feature.

But proof-by-current-implementation-of-other-languages can’t be any
better…

The only “implementation limitations” discussed here are that
integers are immediate values. No problems arise from this - except
that ++ doesn’t behave as in C/Java/Perl. And that’s not even a
problem, just a surprise for some people.

It may not even be a surprise. I don’t think that most people would
care (or even notice) that a hypothetical foo.succ! gave them a
different object back from the one they started with.

They definitely should care and notice. It isn’t a matter of
indifference in Ruby whether a variable refers to this or that object:

a = “x”
b = a
a.extend(SomeModule)
b.succ!
b.some_method_from_Some_Module

Having b.succ! perform a magical, hidden assignment to b (rather than
an in-place incrementation of the object referred to by b) would be
extremely anomalous.

David

···

On Tue, 26 Nov 2002, Simon Cozens wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

OK… I get it… I understood your argument (although
ya cleared up a few other things), but I still just
didn’t GET why you couldn’t do a ‘++’ method that
simply did something like ‘self = self.succ’

Of course, after actually TRYING that on my own (the
best learning tool ;), I find that I can’t modify
self. I guess that makes sense.

And I assume Ruby doesn’t want to go the way of C# and
have safe vs. unsafe data, right? How bad would it be
to have a an ‘unsafe’ object that COULD modify self?

Ah well, this is all pretty pointless for me anyway.
I’ve been a C/C++ programmer for nearly a decade now,
and I haven’t missed an increment/decrement operator
one bit since trying Ruby.

I love this language :wink:

Jason

···

— “Hal E. Fulton” hal9000@hypermetrics.com wrote:

----- Original Message -----
From: “Jason Persampieri” helgaorg@yahoo.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, November 25, 2002 10:15 PM
Subject: Re: Things That Newcomers to Ruby Should
Know (11/24/02)

I mean, C doesn’t allow 3++ either (well, it may
ALLOW
it, but it doesn’t mean anything). I think that
argument is pretty bogus.

It’s not bogus at all. It’s just a simpler
way of illustrating the fact that Ruby
operators operate on objects, not variables.

This is the same argument, using a variable
instead of a constant.

x = 3
y = 3
x++
puts y # 4???

Hal

Hi Jason,

Let me try to clear things up. Theoretically, it is not impossible to
be able to write in some non-standard Ruby

x = 5
y = 5
x.succ!    # -> x == 6, y == 5

in which case x and y actually have different id’s. This can be
accomplised if all objects/variables had simply been implemented as
VALUE which is a pointer. I think this is done in some other languages
such as Tcl and Python.

However, practically we cannot do it in the current Ruby C
implementation, because [Fixnum, Symbol, true, false, nil] have been
implemented as VALUE which is an immediate object. (Each object
is a “singleton” if you want to call it that way.) I guess Matz created
the “immediate objects” for efficiency reason, but this has the
consequence of the impossibility to have x.succ! if x is a Fixnum.

Ruby is not 100% efficiency (something like C) and neither 100% consitency
(something like Smalltalk). I think it is really a careful balance
between the two.

Regarding assignments of type ‘self = something’, you cannot do it in
Ruby, but for objects which are not immediate, at least in theory you can
do it if you use the Ruby C API’s.

Regards,

Bill

P.S. I don’t know what happens in the Java implementation of Ruby (JRuby),
whether it distinguishes between VALUE as pointer and as immediate object,
as Java does not have pointers in the C sense.

···

Jason Persampieri helgaorg@yahoo.com wrote:

OK… I get it… I understood your argument (although
ya cleared up a few other things), but I still just
didn’t GET why you couldn’t do a ‘++’ method that
simply did something like ‘self = self.succ’

Hi –

···

On Wed, 27 Nov 2002, William Djaja Tjokroaminata wrote:

Jason Persampieri helgaorg@yahoo.com wrote:

OK… I get it… I understood your argument (although
ya cleared up a few other things), but I still just
didn’t GET why you couldn’t do a ‘++’ method that
simply did something like ‘self = self.succ’

Hi Jason,

Let me try to clear things up. Theoretically, it is not impossible to
be able to write in some non-standard Ruby

x = 5
y = 5
x.succ!    # -> x == 6, y == 5

in which case x and y actually have different id’s. This can be
accomplised if all objects/variables had simply been implemented as
VALUE which is a pointer. I think this is done in some other languages
such as Tcl and Python.

However, practically we cannot do it in the current Ruby C
implementation, because [Fixnum, Symbol, true, false, nil] have been
implemented as VALUE which is an immediate object. (Each object
is a “singleton” if you want to call it that way.) I guess Matz created
the “immediate objects” for efficiency reason, but this has the
consequence of the impossibility to have x.succ! if x is a Fixnum.

I think there’s a point at which it’s OK to say that something is a
characteristic of Ruby, not just of the current Ruby implementation,
and this is probably it :slight_smile:

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

dblack@candle.superlink.net wrote:

I think there’s a point at which it’s OK to say that something is a
characteristic of Ruby, not just of the current Ruby implementation,
and this is probably it :slight_smile:

Hi David,

Two things:

  1. In my opinion, it is really a consequence of Ruby implementation; for
    people who keeps asking why, probably it is the ultimate answer. Ruby
    will continue to work as now even if all the objects/variables are simply
    implemented as VALUE of type pointer (no “immediate” objects).

  2. I don’t know what the consequence is in JRuby. This is related to the
    fundamental question, “what is Ruby”?

Regards,

Bill

William Djaja Tjokroaminata billtj@z.glue.umd.edu writes:

  1. In my opinion, it is really a consequence of Ruby implementation; for
    people who keeps asking why, probably it is the ultimate answer.
    Ruby will continue to work as now even if all the objects/variables
    are simply implemented as VALUE of type pointer (no “immediate”
    objects).

I believe it’s a question of Ruby design, not implementation.

Ruby has reference semantics for all assignment:

b = a
c = b

leaves b and c referencing the same object, regardless of that
object’s type.

Now, if ‘a’ happens to be a Fixnum, that would lead to a problem if
Fixnum supported mutators:

a = 1

sometime later

b = a
c = b

b++

(or b.succ! or whatever)

This would change the object referenced by both ‘b’ and ‘c’ (and ‘a’),
and hence the value of ‘1’ would be changed.

This already happens with (say) Strings, and every now and then it
causes a surprise (read bug). It happens to me perhaps once every
couple of weeks. Because of this, I’d personally rather have seen
immutable Strings being the default in Ruby (it would also make string
assignment from a constant slightly more efficient).

However, Matz clearly believed that although Strings could be mutable,
having integers whose value changes out from beneath you was a BAD
IDEA. So, he made Fixnums immutable. Having done that, he was then
free to make them value objects.

So, Fixnums (and the rest) are immutable first, value objects
second. The reason they’re immutable is not an implementation
decision, but a language design issue.

Dave

Hi Dave,

Thanks a lot for the comprehensive explanation. How about Bignums
then? :slight_smile: (efficiency vs. consistency vs. implementation vs. …)

Regards,

Bill

···

Dave Thomas Dave@pragmaticprogrammer.com wrote:

However, Matz clearly believed that although Strings could be mutable,
having integers whose value changes out from beneath you was a BAD
IDEA. So, he made Fixnums immutable. Having done that, he was then
free to make them value objects.

So, Fixnums (and the rest) are immutable first, value objects
second. The reason they’re immutable is not an implementation
decision, but a language design issue.

William Djaja Tjokroaminata billtj@z.glue.umd.edu writes:

···

Dave Thomas Dave@pragmaticprogrammer.com wrote:

However, Matz clearly believed that although Strings could be mutable,
having integers whose value changes out from beneath you was a BAD
IDEA. So, he made Fixnums immutable. Having done that, he was then
free to make them value objects.

So, Fixnums (and the rest) are immutable first, value objects
second. The reason they’re immutable is not an implementation
decision, but a language design issue.

Hi Dave,

Thanks a lot for the comprehensive explanation. How about Bignums
then? :slight_smile: (efficiency vs. consistency vs. implementation vs. …)

Same goes for Bignums (they also are not mutable). I’m not sure what
you’re getting at.

Dave

Hi Dave,

I guess probably it is true that for now we have to put the implementation
issue aside. Well, then probably the question is, given the Ruby built-in
classes, officially which are mutable and which are immutable and
why? This is because one of the posters stated that to him it seems that
the mutability designation is arbitrary (i.e., some work for chars
(strings of length one) but not for Fixnums).

I don’t think the concept of mutability is ever mentioned in the pickaxe
book. In “Python Essential Reference”, for example, the concept of
mutability is introduced early, and it seems that in Python (at least in
version 1.5.2) only lists (arrays) and dictionaries (hashes) are mutable.

When I used Python, the fact that a string is immutable annoyed me. But
like you said, it can be very useful to prevent bugs. Right now, I think
the problem is not whether Fixnums and strings (and others) should be
mutable or immutable (so far it seems there is no concensus, at least for
strings), but the plain fact, that in Ruby, it seems the concept of
immutability is never treated in a formal way. I think this is why this
thread has become so long; each person has his own idea why Fixnums are
immutable while strings are mutable. I think it will suffice for all of
us if Matz simply gives the formal list of which objects/classes are
mutable and immutable. I agree with you that the implementation is
secondary.

Regards,

Bill

···

Dave Thomas Dave@pragmaticprogrammer.com wrote:

Same goes for Bignums (they also are not mutable). I’m not sure what
you’re getting at.

William Djaja Tjokroaminata billtj@y.glue.umd.edu writes:

I don’t think the concept of mutability is ever mentioned in the pickaxe
book. In “Python Essential Reference”, for example, the concept of
mutability is introduced early, and it seems that in Python (at least in
version 1.5.2) only lists (arrays) and dictionaries (hashes) are mutable.

I’d be surprised if File was immutable :slight_smile:

I think it will suffice for all of us if Matz simply gives the
formal list of which objects/classes are mutable and immutable. I
agree with you that the implementation is secondary.

I don’t see why we need to waste Matz’s time producing this list. It’s
clear which methods change an object’s state.

My point was that you were giving the impression that the lack of ++
for Fixnum was an implementation issue, and that alternative Ruby
implementations might support it. Given that you produce a document
aimed at newcomers, it was important to me that this misunderstanding
was cleared up.

Cheers

Dave

Hello William,

Wednesday, November 27, 2002, 7:47:36 PM, you wrote:

immutable while strings are mutable. I think it will suffice for
all of us if Matz simply gives the formal list of which
objects/classes are mutable and immutable. I agree with you that
the implementation is secondary.

this list implicitly exists - there is a convenience that only methods
with names ending with “!” change “self”. of course, there is a number
of exceptions (“<<”, for example) and someone can use another names
for slef-modifyiyng methods

i know, it it the not exactly what you ask for, but in current stage
immutable object is just any object which don’t have self-changing
methods. Bignum, for example. Just until you add (c-implemented)
“next!” method or smth like this

···


Best regards,
Bulat mailto:bulatz@integ.ru

Well, as you already read, different people gave different reasons why
Fixnum#succ! is “impossible”. Without the concept of “immutability” being
formally introduced in the Ruby programming language, I can always give
the reason from the implementation point of view. (In theory, I can make
Fixnum to be mutable; whether this is good or bad is a different
story. Guido thought that strings should be immutable; Matz thought
otherwise. Python insists that hash keys be immutable objects; Ruby
allows any objects, with the consequence of the need for “rehash” in
certain situations.)

Without any formal treatment of immutability in Ruby, your previous post
is the only reference that I can use if in the future these questions are
asked again:

  1. Why Fixnum is immutable (no Fixnum#succ!) while String is mutable
    (String#.succ! is provided)?

  2. How do I know which objects/classes are mutable and
    immutable? (Answer: just read all the methods, and if no “!” methods are
    provided, it is immutable (?))

Regards,

Bill

···

Dave Thomas Dave@pragmaticprogrammer.com wrote:

My point was that you were giving the impression that the lack of ++
for Fixnum was an implementation issue, and that alternative Ruby
implementations might support it. Given that you produce a document
aimed at newcomers, it was important to me that this misunderstanding
was cleared up.

Hi,

  1. Why Fixnum is immutable (no Fixnum#succ!) while String is mutable
    (String#.succ! is provided)?

Numbers are immutable. Partially because of performance. Partially
because of Ruby’s object model. In Ruby, objects are values, not
place holders, so that numbers themselves are naturally immutable.

  1. How do I know which objects/classes are mutable and
    immutable? (Answer: just read all the methods, and if no “!” methods are
    provided, it is immutable (?))

You don’t have to care in general. If you can’t change the state of
the object, it is immutable.

						matz.
···

In message “Re: Things That Newcomers to Ruby Should Know (11/24/02)” on 02/11/28, William Djaja Tjokroaminata billtj@y.glue.umd.edu writes: