Forum: Ruby Method that mutates object

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
C3462eedb10f5fe0178c4ef76b0a1357?d=identicon&s=25 jay s. (solomon)
on 2011-05-25 21:22
Say we want to write a String method called clear that takes a given
string and modifies that string to be equal to "".

Ex.

str = "string"

we call str.clear and we get back "", not just "" printed to the screen,
but the value of str is now "" (mutate the original string).


I understand that the following code would just print "" to the screen
but not modify the actual str object.

class String
  def clear
    ""
  end
end


How would you write a method that actually modifies the str object?
C40020a47c6b625af6422b5b1302abaf?d=identicon&s=25 Stefano Crocco (crocco)
on 2011-05-25 21:30
(Received via mailing list)
On Thursday 26 May 2011 04:22:46 jason solomon wrote:
>
> How would you write a method that actually modifies the str object?
This should do what you want

class String

  def clear
    replace ''
  end

end

Stefano
99804651e19d8b0dffbc0da53e39114e?d=identicon&s=25 Adam Prescott (Guest)
on 2011-05-25 21:32
(Received via mailing list)
On Wed, May 25, 2011 at 8:22 PM, jason solomon
<solomon.jas@gmail.com>wrote:

>
String#replace

s1 = s2 = ""
s2.replace("foo")
s2 #=> "foo"
s1.object_id == s2.object_id

def String
  def fooify
    replace("foo")
  end
end

s = "bar"
s.fooify
s == "foo"
85991f138ede6236f35eb98da22b7b01?d=identicon&s=25 Marvin Gülker (quintus)
on 2011-05-25 22:46
(Received via mailing list)
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Am 25.05.2011 21:22, schrieb jason solomon:
>
> How would you write a method that actually modifies the str object?
>

Just in addition to what the others said, the method String#clear
already exists.

=================================================
$ ri String#clear
= String#clear

(from ruby core)
-
------------------------------------------------------------------------------
  string.clear    ->  string

-
------------------------------------------------------------------------------

Makes string empty.

       a = "abcde"
       a.clear    #=> ""
=================================================

And does exactly what you want it to.

Vale,
Marvin
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJN3WptAAoJELh1XLHFkqhaG5AH/1mAcLBo9eKzpJg3XHjIXXAr
vFOUV9+Ow3hSBZ8Q1KDQrKOVd2QBRkkA2vk7wF7H9KrJCar7wElf0OgJHYmjlEhR
HRnnxtoRgdkRo1GoFyvGr7tRzoKlAgPNC93AQFDm7mZFfO6QMtF5aR4xLgWMIZhM
vRNMkjs71XE1lmxASvFDVgW4SS1wxJnzDe0LQZncjOOPaZHQQM2P3aR9mHL8Or8O
FBvuzqgCptKq5Y69xv/AysLZlRu1ja37J6ggK7LIuLsmT2UaydOc9pVgDaunazrI
ym9IASTm/7vmYRKr3FuA98JifEGAEWC6jkuP0MYcLNkGLdhEzkce04FxHdkfodk=
=5xGw
-----END PGP SIGNATURE-----
C3462eedb10f5fe0178c4ef76b0a1357?d=identicon&s=25 jay s. (solomon)
on 2011-05-25 22:50
Stefano Crocco wrote in post #1001011:
> On Thursday 26 May 2011 04:22:46 jason solomon wrote:
>>
>> How would you write a method that actually modifies the str object?
> This should do what you want
>
> class String
>
>   def clear
>     replace ''
>   end
>
> end
>
> Stefano



Thanks for the reply.  Say we wanted to write our own replace method and
not use the replace method provided by the String class?
C3462eedb10f5fe0178c4ef76b0a1357?d=identicon&s=25 jay s. (solomon)
on 2011-05-25 22:59
I know this is changing gears a little here, but the previous post
reminded me of this.

Say I want to extend the built in Array class with some useless function
called crazy()

class Array
  def crazy
    ...do something...
  end
end


Correct me if I'm wrong, but I now have a class method for Array.  I
call Array.methods just to make sure that it is there, yet it doesn't
show up, however if I do this:

a = []

and then call a.methods, I can see the crazy() method that we wrote
available.  It looks to me as if I am creating an instance method, but I
would think I would do that like this:

def a.crazy
  ...do something...
end


Does this issue have anything to do with the face that the Array class
is immutable?

I'm a bit confused, any help.  Thanks.
C3462eedb10f5fe0178c4ef76b0a1357?d=identicon&s=25 jay s. (solomon)
on 2011-05-25 23:03
Marvin Gülker wrote in post #1001033:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Am 25.05.2011 21:22, schrieb jason solomon:
>>
>> How would you write a method that actually modifies the str object?
>>
>
> Just in addition to what the others said, the method String#clear
> already exists.
>
> =================================================
> $ ri String#clear
> = String#clear
>
> (from ruby core)
> -
> ------------------------------------------------------------------------------
>   string.clear    ->  string
>
> -
>
------------------------------------------------------------------------------
>
> Makes string empty.
>
>        a = "abcde"
>        a.clear    #=> ""
> =================================================
>
> And does exactly what you want it to.
>
> Vale,
> Marvin
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.11 (GNU/Linux)
> Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
>
> iQEcBAEBAgAGBQJN3WptAAoJELh1XLHFkqhaG5AH/1mAcLBo9eKzpJg3XHjIXXAr
> vFOUV9+Ow3hSBZ8Q1KDQrKOVd2QBRkkA2vk7wF7H9KrJCar7wElf0OgJHYmjlEhR
> HRnnxtoRgdkRo1GoFyvGr7tRzoKlAgPNC93AQFDm7mZFfO6QMtF5aR4xLgWMIZhM
> vRNMkjs71XE1lmxASvFDVgW4SS1wxJnzDe0LQZncjOOPaZHQQM2P3aR9mHL8Or8O
> FBvuzqgCptKq5Y69xv/AysLZlRu1ja37J6ggK7LIuLsmT2UaydOc9pVgDaunazrI
> ym9IASTm/7vmYRKr3FuA98JifEGAEWC6jkuP0MYcLNkGLdhEzkce04FxHdkfodk=
> =5xGw
> -----END PGP SIGNATURE-----





Correct me if I am wrong, String#clear does not exist in Ruby 1.8 and
earlier.
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (candlerb)
on 2011-05-25 23:20
jay s. wrote in post #1001040:
> Say I want to extend the built in Array class with some useless function
> called crazy()
>
> class Array
>   def crazy
>     ...do something...
>   end
> end
>
>
> Correct me if I'm wrong, but I now have a class method for Array.

You're wrong, so I'll correct you :-) "def" creates instance methods.
You now have a new instance method on class Array; that is, a method
which is available to all objects which are instances of Array.

> I
> call Array.methods just to make sure that it is there, yet it doesn't
> show up, however if I do this:
>
> a = []
>
> and then call a.methods, I can see the crazy() method that we wrote
> available.

Yes. To call that method, you'd do "a.crazy"

> It looks to me as if I am creating an instance method, but I
> would think I would do that like this:
>
> def a.crazy
>   ...do something...
> end

That would create a singleton method: a method which belongs only to
that object.

a = []
def a.crazy
  puts "hello"
end
a.crazy   # works

b = []
b.crazy   # NoMethodError

What you did before was this:

class Array
  def crazy
    ...
  end
end

That defines an instance method on class Array - that is, a method which
is available to all array objects, even arrays which existed before you
defined the method. This is the "normal" sort of method you define when
programming.

Just to close the loop, here's how you do class methods:

def Array.crazy
  puts "wibble"
end

Array.crazy

Now, that syntax may look familiar. In Ruby, classes are objects. You
are defining a singleton method on the object "Array" (which also
happens to be an object of class "Class")

So, "class methods" are nothing more than singleton methods, on an
object of class Class.

> Does this issue have anything to do with the face that the Array class
> is immutable?

No, and in any case the class Array is definitely *not* immutable.

$ irb --simple-prompt
>> a = [1,2]
=> [1, 2]
>> a << 3
=> [1, 2, 3]
>> a
=> [1, 2, 3]

> I'm a bit confused

That does appear to be the case :-) You might want to work through some
documentation. This one is good:
http://www.ruby-doc.org/docs/ProgrammingRuby/

And continue experimenting within irb of course.

Regards,

Brian.
C3462eedb10f5fe0178c4ef76b0a1357?d=identicon&s=25 jay s. (solomon)
on 2011-05-25 23:36
Thank you for the help, that actually cleared up quite a bit for me.
54404bcac0f45bf1c8e8b827cd9bb709?d=identicon&s=25 7stud -- (7stud)
on 2011-05-26 00:00
jay s. wrote in post #1001051:
> Thank you for the help, that actually cleared up quite a bit for me.
>

Here's some more. This line:

> Array.methods

asks the question, "What methods does Array respond to?"  It does not
ask, "What methods do the instances of the Array class respond to?"
Array is a class, and in ruby a class is an object/instance of a class
called Class.  In fact, every class in ruby is an instance of Class, and
as such, a class object responds to instance methods defined
in Class(and its superclasses: Module and Object, and Kernel which
Object includes. The methods() method is defined in Kernel).  The most
common instance method that a class object calls is...new().

Now here is the confusing part, Class is a class, and because all
classes in ruby are objects/instances of the Class class, the Class
object itself is an instance of Class--in other words, the Class object
is an instance of itself. Presto. lol.  Don't even try to understand
that--but the logic is consistent.
C3462eedb10f5fe0178c4ef76b0a1357?d=identicon&s=25 jay s. (solomon)
on 2011-05-26 15:50
Thanks again for all replies as it has helped me to wrap my head around
some of the problems that I've experienced.

Say we wanted to write our own replace method and not use the replace
method provided by the String class?  So we want to write a method that
takes a string object and modifies/mutates that same object and then
returns it, without creating a copy of that object.
C5e056d4888f81842e966ff308c03416?d=identicon&s=25 Jeremy Bopp (Guest)
on 2011-05-26 16:44
(Received via mailing list)
On 5/26/2011 08:56, jay s. wrote:
> Say we wanted to write our own replace method and not use the replace
> method provided by the String class?  So we want to write a method that
> takes a string object and modifies/mutates that same object and then
> returns it, without creating a copy of that object.

What exactly are you trying to accomplish?  The String class provides
multiple methods to mutate the String instance in various ways, and many
of those methods could be specified in terms of the others, including
replace.  Rather than ask someone to figure out another solution to
which you may respond, "and how do we write our own method_x and not use
the method_x provided by the String class," could you provide some
details about your goals?  What kind of modifications on the String
instance do you want your method to perform?  What methods provided by
the String class are out of bounds (as replace apparently is)?

To me this is sounding a bit like a homework assignment, but maybe it's
not.  In any case, the documentation for the String class is actually
pretty good, so you can probably answer your own question with a little
easy reading:

http://rdoc.info/stdlib/core/1.9.2/String

If I understand what you're really trying to accomplish, the method you
want is definitely listed there.

-Jeremy
C3462eedb10f5fe0178c4ef76b0a1357?d=identicon&s=25 jay s. (solomon)
on 2011-05-26 17:00
Jeremy Bopp wrote in post #1001249:
> On 5/26/2011 08:56, jay s. wrote:
>> Say we wanted to write our own replace method and not use the replace
>> method provided by the String class?  So we want to write a method that
>> takes a string object and modifies/mutates that same object and then
>> returns it, without creating a copy of that object.
>
> What exactly are you trying to accomplish?  The String class provides
> multiple methods to mutate the String instance in various ways, and many
> of those methods could be specified in terms of the others, including
> replace.  Rather than ask someone to figure out another solution to
> which you may respond, "and how do we write our own method_x and not use
> the method_x provided by the String class," could you provide some
> details about your goals?  What kind of modifications on the String
> instance do you want your method to perform?  What methods provided by
> the String class are out of bounds (as replace apparently is)?
>
> To me this is sounding a bit like a homework assignment, but maybe it's
> not.  In any case, the documentation for the String class is actually
> pretty good, so you can probably answer your own question with a little
> easy reading:
>
> http://rdoc.info/stdlib/core/1.9.2/String
>
> If I understand what you're really trying to accomplish, the method you
> want is definitely listed there.
>
> -Jeremy


Just for clarification, this is by no means a homework assignment.  I am
new to Ruby and I'm trying to get a better grasp on how Ruby handles
mutation.  I actually think at this point I'll try looking at Ruby's
source code and see how String#replace is implemented.  Maybe I'm just
over complicating my question.
C3462eedb10f5fe0178c4ef76b0a1357?d=identicon&s=25 jay s. (solomon)
on 2011-05-26 17:55
/*
 *  call-seq:
 *     str.replace(other_str)   -> str
 *
 *  Replaces the contents and taintedness of <i>str</i> with the
corresponding
 *  values in <i>other_str</i>.
 *
 *     s = "hello"         #=> "hello"
 *     s.replace "world"   #=> "world"
 */

VALUE
rb_str_replace(VALUE str, VALUE str2)
{
    str_modifiable(str);
    if (str == str2) return str;

    StringValue(str2);
    str_discard(str);
    return str_replace(str, str2);
}



So from the looks of it the String#replace method is implemented in C,
and I'm assuming the return value of rb_str_replace is VALUE?
C3462eedb10f5fe0178c4ef76b0a1357?d=identicon&s=25 jay s. (solomon)
on 2011-05-26 18:07
I understand that using String#replace works for the String class, but
what if you were writing a random method for Integer that takes a number
and sets it equal to some other number.

Ex.

x = 7

class Integer
  def crazy
    ...set x to 5...
  end
end


now when you call x the value is 5
C5e056d4888f81842e966ff308c03416?d=identicon&s=25 Jeremy Bopp (Guest)
on 2011-05-26 18:18
(Received via mailing list)
On 5/26/2011 11:07, jay s. wrote:
>     ...set x to 5...
>   end
> end
>
>
> now when you call x the value is 5

Instances of Integer are immutable, so you can't do that.  The
documentation for Fixnum (a descendant of Integer) mentions this in the
Overview section:

http://rdoc.info/stdlib/core/1.9.2/Fixnum

-Jeremy
C3462eedb10f5fe0178c4ef76b0a1357?d=identicon&s=25 jay s. (solomon)
on 2011-05-26 18:30
Jeremy Bopp wrote in post #1001275:
> On 5/26/2011 11:07, jay s. wrote:
>>     ...set x to 5...
>>   end
>> end
>>
>>
>> now when you call x the value is 5
>
> Instances of Integer are immutable, so you can't do that.  The
> documentation for Fixnum (a descendant of Integer) mentions this in the
> Overview section:
>
> http://rdoc.info/stdlib/core/1.9.2/Fixnum
>
> -Jeremy




Thanks.
161289732b5b8c9dcb5834a3f0535340?d=identicon&s=25 Chad Perrin (Guest)
on 2011-05-26 19:43
(Received via mailing list)
On Fri, May 27, 2011 at 12:00:43AM +0900, jay s. wrote:
>
> Just for clarification, this is by no means a homework assignment.  I am
> new to Ruby and I'm trying to get a better grasp on how Ruby handles
> mutation.  I actually think at this point I'll try looking at Ruby's
> source code and see how String#replace is implemented.  Maybe I'm just
> over complicating my question.

For that, you might want to look at the source for String#replace in the
Rubinius implementation of Ruby.

    https://github.com/evanphx/rubinius
B31e7abd14f1ceb4c4957da08933c630?d=identicon&s=25 Josh Cheek (josh-cheek)
on 2011-05-26 20:13
(Received via mailing list)
On Thu, May 26, 2011 at 12:41 PM, Chad Perrin <code@apotheon.net> wrote:
>
>    https://github.com/evanphx/rubinius
>
> --
> Chad Perrin [ original content licensed OWL: http://owl.apotheon.org ]
>

Since it took me about 10 minutes to look up, here is the actual link:

https://github.com/evanphx/rubinius/blob/84264ce51...
E7559e558ececa67c40f452483b9ac8c?d=identicon&s=25 Gary Wright (Guest)
on 2011-05-26 23:40
(Received via mailing list)
On May 26, 2011, at 12:07 PM, jay s. wrote:

>    ...set x to 5...
>  end
> end
>
>
> now when you call x the value is 5


This seems like a simple question but it touches on some very deep
issues of Ruby's object model.  Understanding the object model is the
key to understanding why your question doesn't make sense in Ruby.

Ruby's fixnum objects are not containers for an integer value.  This
means that for any particular fixnum object there is no way to alter it
so that it no longer behaves like a 7 and instead behaves like a 5, for
example.  The integer semantics of a fixnum object are defined by the
object's *identity*, not by any state it carries around (i.e. instance
variables or state that is hidden from the programmer but maintained by
the runtime).

>> x = 5       #=> 5
>> x.object_id #=> 11
>> y = 7       #=> 7
>> y.object_id #=> 15
>> z = 3 + 4   #=> 7
>> z.object_id #=> 15
>> z.eql?(y)   #=> true

In that example you can see that y and z reference the *same* object,
which happens to be object 15 in my version of Ruby and which happens to
behave like the integer 7.  The Ruby runtime ensures that object 15
always behaves like the integer 7 and that it is the *only* object that
behaves like the integer 7.

And yes, you can attach instance variables to fixnum objects:

>> a = 2 #=> 2
>> b = 1 + 1 #=> 2
>> a.instance_variable_set('@english', 'two') #=> "two"
>> b.instance_variable_get('@english') #=> "two"
>> a.object_id #=> 5
>> b.object_id #=> 5

So you can see that within Ruby's object model there is one and only one
fixnum object that behaves like the integer 2.  That particular object
in MRI Ruby 1.9.2 happens to have an object_id of 5, but that is really
just an implementation detail.

Lots and lots of Rubyists describe fixnum objects as 'immutable', but as
shown above with instance variables, that is simply not an accurate
description of Ruby's fixnum objects. The characteristic that
erroneously gets labeled as 'immutability' is that the semantics of a
fixnum object are defined by its *identity* and not by its state.  A
consequence of this property is that having a *reference* to a fixnum is
all you need to interact with the object. The underlying object doesn't
even have to 'exist' within the runtime (i.e. there is no memory
allocated for every fixnum object).  The runtime can emulate the
behavior of fixnum objects simply by manipulating the *references*
without ever instantiating the objects.  See
<http://en.wikipedia.org/wiki/Tagged_pointer> for more about how this
sort of thing is implemented.  There are several other Ruby classes that
have this behavior and tend to be implemented in this way:  nil, true,
false from NilClass, TrueClass, and FalseClass respectively and symbols.

Going back to your original question about setting x to a new value.
Another way of interpreting that request is not that you are mutating
the object that x references but instead you are rebinding the variable
x to a different object. Ruby variables are simply named containers for
object references so if you can replace the reference to the fixnum 7
associated with variable x with a reference to the fixnum 5, you will
have 'set x to 5', which is exactly what Ruby's assignment operation
does.

There are a variety of ways for a Ruby method to gain access to variable
bindings that are out of the direct scope of the method but it is
generally considered bad form for a method to alter variable bindings
outside its scope.  Nevertheless, here is one way to do it:

class Integer
  def assign(name, value, binding_object)
    eval "#{name} = #{value}", binding_object
  end
end

>> x = 5                     #=> 5
>> x.assign('x', 7, binding) #=> 7
>> x                         #=> 7

This sort of use of eval and binding is *not* at all common and probably
only comes into play with various debugging or programming tools rather
than in the normal course of writing Ruby programs.


Gary Wright
99804651e19d8b0dffbc0da53e39114e?d=identicon&s=25 Adam Prescott (Guest)
on 2011-05-27 17:58
(Received via mailing list)
On 26 May 2011 22:40, "Gary Wright" <gwtmp01@mac.com> wrote:
>
> There are a variety of ways for a Ruby method to gain access to variable
bindings that are out of the direct scope of the method but it is
generally
considered bad form for a method to alter variable bindings outside its
scope.  Nevertheless, here is one way to do it:
>
> This sort of use of eval and binding is *not* at all common and probably
only comes into play with various debugging or programming tools rather
than
in the normal course of writing Ruby programs.

Not to needlessly self-promote or anything, but I recently wrote about
variables and bindings, so perhaps this is informative:

http://aprescott.com/posts/variables-closures-and-scope
D7463bd611f227cfb2ef4da4a978a203?d=identicon&s=25 Christopher Dicely (Guest)
on 2011-05-28 20:06
(Received via mailing list)
On Thu, May 26, 2011 at 2:34 PM, Gary Wright <gwtmp01@mac.com> wrote:
>>
> This seems like a simple question but it touches on some very deep issues of
Ruby's object model.  Understanding the object model is the key to understanding
why your question doesn't make sense in Ruby.
>
>
> So you can see that within Ruby's object model there is one and only one fixnum
object
> that behaves like the integer 2.  That particular object in MRI Ruby 1.9.2
happens to have an
> object_id of 5, but that is really just an implementation detail.
>
> Lots and lots of Rubyists describe fixnum objects as 'immutable', but as shown
above with
> instance variables, that is simply not an accurate description of Ruby's fixnum
objects. The
> characteristic that erroneously gets labeled as 'immutability' is that the
semantics of a fixnum object
> are defined by its *identity* and not by its state.

That's actually probably not the best description. While its true that
the implementation of the immutability of the arithmetic value of a
Fixnum is implemented (in most and possibly all Ruby implementations)
through a fixed relationship of that value on the identity of the
Fixnum, its worth noting that the value of a Bignum in an arithmetic
context is likewise not dependent on its state, even though Bignums --
unlike Fixnums -- are generally not implemented with a fixed
relationship between value and identity, such that there can be more
than one Bignum object with the same value.

The real enforcement of the distinction isn't so much that identity
rather than state is used (since this is not true of the
implementation of Bignums) but that you can't define singleton methods
on objects of the built-in numeric types, and the arithmetic value
isn't stored in mutable state (that is, its not in instance
variables), so the arithmetic behavior of objects of built-in numeric
types can't be overridden on an object-by-object basis by the normal
methods Ruby allows for doing that for object behavior. That Fixnums
of the same value share object identity is an implementation detail,
not the fundamental basis of the arithmetic immutability, since the
latter is a feature of Ruby's built-in numerics generally, including
those that don't use Fixnum-style identity-sharing.
E7559e558ececa67c40f452483b9ac8c?d=identicon&s=25 Gary Wright (Guest)
on 2011-05-29 02:30
(Received via mailing list)
On May 28, 2011, at 2:05 PM, Christopher Dicely wrote:
> That's actually probably not the best description. While its true that
> the implementation of the immutability of the arithmetic value of a
> Fixnum is implemented (in most and possibly all Ruby implementations)
> through a fixed relationship of that value on the identity of the
> Fixnum, its worth noting that the value of a Bignum in an arithmetic
> context is likewise not dependent on its state, even though Bignums --
> unlike Fixnums -- are generally not implemented with a fixed
> relationship between value and identity, such that there can be more
> than one Bignum object with the same value.

My main point was that 'immutable' is the wrong term to apply to
fixnum objects (and all other objects) in Ruby.  You can add instance
variables to anything.

The original poster asked how to change a fixnum representing the
integer 7 to a fixnum representing the integer 5, which you can't
do because fixnum semantics are based on identity, not state.

You are correct that in the bignum case you also can't mutate a
bignum object so that it behaves like a different integer but for
different implementation reasons.  In this case, the integer semantics
of a bignum are carried around in hidden state that is not accessible
to the Ruby programmer.  You said that the "value..is not dependent
on its state" but I think you meant that the value is not dependent
on the "visible" state or "programmer accessible" state.

Float is another class that implements its semantics via hidden state.

      identity  hidden-state  hidden-state
      semantics semantics     accessible?
fixnum yes       no            no
symbol yes       no            no
float  no        yes           no
bignum no        yes           no
string no        yes           yes (e.g. String#replace)

> The real enforcement of the distinction isn't so much that identity
> rather than state is used (since this is not true of the
> implementation of Bignums) but that you can't define singleton methods
> on objects of the built-in numeric types.

I'm not sure what singleton methods have to do with the earlier
discussion.  The reason you can't define singleton methods on Fixnum
instances and other core objects is that it would introduce horrible
performance penalties, not that there is something semantically
awkward about it.  In fact its absence is what is awkward.

> That Fixnums of the same value share object identity is an implementation
detail,
> not the fundamental basis of the arithmetic immutability, since the
> latter is a feature of Ruby's built-in numerics generally, including
> those that don't use Fixnum-style identity-sharing.

The reason that I think the behavior of Fixnum, Symbol, NilClass,
TrueClass, and FalseClass should be understand in the context of
identity semantics is because that property manifests itself in the
way that the equality methods work.

For the 'identity' classes I listed above,
a == b if and only if a.equal?(b)

For the other built-in numerics with 'hidden' state that isn't true,
the rule is a bit more relaxed:
a.equal?(b) implies a == b  (but not the other way around)

There are also performance implications associated with these
implementation
details.  For example symbol equality can be determined by comparing
references
while string equality cannot.

Gary Wright
161289732b5b8c9dcb5834a3f0535340?d=identicon&s=25 Chad Perrin (Guest)
on 2011-05-29 02:51
(Received via mailing list)
On Sun, May 29, 2011 at 09:29:41AM +0900, Gary Wright wrote:
>
> My main point was that 'immutable' is the wrong term to apply to
> fixnum objects (and all other objects) in Ruby.  You can add instance
> variables to anything.

I must be doing something wrong, then:

    irb(main):001:0> module Mod
    irb(main):002:1> end
    => nil
    irb(main):003:0> bar = 'bar'
    => "bar"
    irb(main):004:0> bar.extend Mod
    => "bar"
    irb(main):005:0> foo = 1
    => 1
    irb(main):006:0> foo.extend Mod
    TypeError: can't define singleton
            from (irb):6:in `extend_object'
            from (irb):6:in `extend'
            from (irb):6
            from /usr/bin/irb1.9.1:12:in `<main>'

. . . and I haven't even tried adding an instance variable to that
module
yet.  How should I add an instance variable to my fixnum object if not
with extend?
E7559e558ececa67c40f452483b9ac8c?d=identicon&s=25 Gary Wright (Guest)
on 2011-05-29 04:12
(Received via mailing list)
On May 28, 2011, at 8:51 PM, Chad Perrin wrote:
> . . . and I haven't even tried adding an instance variable to that module
> yet.  How should I add an instance variable to my fixnum object if not
> with extend?

We are talking about two different things.  You are talking about
modifying the singleton class, which you can't do.  It is prohibited
because it would kill performance to dispatch through singleton classes
for some of the core data types.

But you can manually add instance variables:

3.instance_variable_set("@english", "three")


Or you can modify the Fixnum class:

class Fixnum
  attr_accessor :english
end

4.english = "four"

In either case you've got fixnum objects with state that can change.

Gary Wright
161289732b5b8c9dcb5834a3f0535340?d=identicon&s=25 Chad Perrin (Guest)
on 2011-05-29 04:45
(Received via mailing list)
On Sun, May 29, 2011 at 11:06:29AM +0900, Gary Wright wrote:
> end
>
> 4.english = "four"
>
> In either case you've got fixnum objects with state that can change.

Thanks for clearing that up.
6e2eaa4be04b52b937269e7026242242?d=identicon&s=25 Henrik Johansson (delta99)
on 2016-02-22 11:31
I really like how this post clearly explains the declarative differences
between class and instance methods while keeping it straight on the
point. Nicely done!

Brian Candler wrote in post #1001047:
> jay s. wrote in post #1001040:
>> Say I want to extend the built in Array class with some useless function
>> called crazy()
>>
>> class Array
>>   def crazy
>>     ...do something...
>>   end
>> end
>>

<snip>

>> I'm a bit confused
>
> That does appear to be the case :-) You might want to work through some
> documentation. This one is good:
> http://www.ruby-doc.org/docs/ProgrammingRuby/
>
> And continue experimenting within irb of course.
>
> Regards,
>
> Brian.
02c8490928c5546aaef1ec6f5616f50c?d=identicon&s=25 Kidz Kul (ronn91)
on 2017-04-04 05:04
Wow. cool post. I’d like to write like this too – taking time and real
hard work to make a great article… but I put things off too much and
never seem to get started. Thanks though.http://wordcookiesgame.com/
http://hillclimbracing-2.com/
http://fivenightsatfreddys-4.com/
http://hotmailcomsignin.email/
This topic is locked and can not be replied to.