[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

[Newbie] Immutable objects

Einar Høst

3/9/2006 12:26:00 PM

Hi,

Still working on the basics... for my card game, I want the Card objects
to be immutable. Is it sufficient to put 'freeze' in the end of the
constructor, like this (suit and rank will be strings):

def initialize(suit, rank)
@suit, @rank = suit, rank
freeze
end

Thanks,
Einar
9 Answers

Robert Klemme

3/9/2006 2:35:00 PM

0

Einar Høst wrote:
> Hi,
>
> Still working on the basics... for my card game, I want the Card
> objects to be immutable. Is it sufficient to put 'freeze' in the end
> of the constructor, like this (suit and rank will be strings):
>
> def initialize(suit, rank)
> @suit, @rank = suit, rank
> freeze
> end

It's not sufficient, you'll have to freeze those strings, too. Note that
this will freeze the originals which probably is a bad idea. You could do

def ini(suit, rank)
@suit = suit.dup.freeze
@rank = rank.dup.freeze
freeze
end

In practice I believe it's rarely seen that people actually use freeze.

HTH

robert

James Gray

3/9/2006 2:49:00 PM

0

On Mar 9, 2006, at 6:23 AM, Einar Høst wrote:

> Hi,
>
> Still working on the basics... for my card game, I want the Card
> objects to be immutable. Is it sufficient to put 'freeze' in the
> end of the constructor, like this (suit and rank will be strings):
>
> def initialize(suit, rank)
> @suit, @rank = suit, rank
> freeze
> end

As a Ruby rule of thumb, you make an immutable object just by
providing no methods to change the instance data.

Technically, there are ways around that, but there are also ways
around freeze() . Don't lose a lot of sleep over these though. If
people don't follow your API, they know they are breaking the rules
and they are responsible for the consequences.

James Edward Gray II

Einar

3/9/2006 3:16:00 PM

0

Robert Klemme wrote:
> Einar Høst wrote:
>
>
> It's not sufficient, you'll have to freeze those strings, too. Note that
> this will freeze the originals which probably is a bad idea. You could do
>
> def ini(suit, rank)
> @suit = suit.dup.freeze
> @rank = rank.dup.freeze
> freeze
> end
>

Ah, I see - in C# "where I come from", strings are immutable. Of course,
no-one will be using this code except me, so I'm definitely conjuring
imaginary problems here - but at the same time, the whole point of this
project is to learn about the language :-)

Thanks!

- Einar

Einar

3/9/2006 3:21:00 PM

0

James Edward Gray II wrote:
> On Mar 9, 2006, at 6:23 AM, Einar Høst wrote:
>
> As a Ruby rule of thumb, you make an immutable object just by providing
> no methods to change the instance data.
>
> Technically, there are ways around that, but there are also ways around
> freeze() . Don't lose a lot of sleep over these though. If people
> don't follow your API, they know they are breaking the rules and they
> are responsible for the consequences.
>
> James Edward Gray II
>

Thanks - that answers my real question, 'how do you make an object
immutable in Ruby'. It's not at all important in this app, which is just
a hobby project for my own amusement and education.

- Einar

George Ogata

3/9/2006 6:53:00 PM

0

Einar <delete.ebuffer@delete.hotmail.com> writes:

> Robert Klemme wrote:
>> Einar Høst wrote:
>> It's not sufficient, you'll have to freeze those strings, too. Note
>> that
>> this will freeze the originals which probably is a bad idea. You could do
>> def ini(suit, rank)
>> @suit = suit.dup.freeze
>> @rank = rank.dup.freeze
>> freeze
>> end
>>
>
> Ah, I see - in C# "where I come from", strings are immutable. Of
> course, no-one will be using this code except me, so I'm definitely
> conjuring imaginary problems here - but at the same time, the whole
> point of this project is to learn about the language :-)

For things like @suit -- which I take it can only take one of four
enumerated values -- I think it's actually more rubyesque to use
symbols. e.g.:

@suit = :spade

This has the side benefit that Symbols themselves are effectively
immutable.

But as Robert and James hinted, freezing is seldom used. It's like
type-checking: you can be a complete nazi about banning anything out
of line, but (a) you lose elegance and simplicity of code and (b) your
tests should probably be checking this anyway. YMMV.

Einar

3/10/2006 8:40:00 AM

0

George Ogata wrote:
> Einar <delete.ebuffer@delete.hotmail.com> writes:
>
>
>>Robert Klemme wrote:
>>
>>>Einar Høst wrote:
>>>It's not sufficient, you'll have to freeze those strings, too. Note
>>>that
>>>this will freeze the originals which probably is a bad idea. You could do
>>>def ini(suit, rank)
>>> @suit = suit.dup.freeze
>>> @rank = rank.dup.freeze
>>> freeze
>>>end
>>>
>>
>>Ah, I see - in C# "where I come from", strings are immutable. Of
>>course, no-one will be using this code except me, so I'm definitely
>>conjuring imaginary problems here - but at the same time, the whole
>>point of this project is to learn about the language :-)
>
>
> For things like @suit -- which I take it can only take one of four
> enumerated values -- I think it's actually more rubyesque to use
> symbols. e.g.:
>
> @suit = :spade
>
> This has the side benefit that Symbols themselves are effectively
> immutable.
>
> But as Robert and James hinted, freezing is seldom used. It's like
> type-checking: you can be a complete nazi about banning anything out
> of line, but (a) you lose elegance and simplicity of code and (b) your
> tests should probably be checking this anyway. YMMV.

Thanks - this is starting to feel like playing an adventure game where
the map of the terrain becomes visible as I explore it (or rather: as
you tell me about it). It looks like symbols are appropriate here. I'm
thinking the same might be the case for rank (e.g. "card value" from 2
up to ace). It might look weird for the numeric values (e.g. :2 or :3 -
which might not even be legal? but then :two and :three would), but not
so for e.g. :jack or :queen.

I'm a bit ambivalent on the strictness issue. I buy your arguments for
a) simplicity and b) testing over typing (Bruce Eckel wrote an article
on that, which made a lot of sense to me). At the same time, I'm still
carrying scars from having a few leaks in the abstractions for a data
access API I wrote in my previous job...

- Einar

Robert Klemme

3/10/2006 9:16:00 AM

0

Einar wrote:
> Thanks - this is starting to feel like playing an adventure game where
> the map of the terrain becomes visible as I explore it (or rather: as
> you tell me about it). It looks like symbols are appropriate here. I'm
> thinking the same might be the case for rank (e.g. "card value" from 2
> up to ace). It might look weird for the numeric values (e.g. :2 or :3
> - which might not even be legal? but then :two and :three would), but
> not so for e.g. :jack or :queen.

Alternatively you could use constants

module Deck
JACK = "jack".freeze
QUEEN = "queen".freeze
...
end

But IMHO symbols are more elegant here. OTOH you can define a specialized
class for this which also holds numeric values

module Deck
CARD = Struct.new :name, :value

def self.card(name, val)
CARD.new(name.freeze,val).freeze
end

QUEEN = card "queen", 10
JACK = card "jack", 11
ACE = card "ace", 100
...
end

> I'm a bit ambivalent on the strictness issue. I buy your arguments for
> a) simplicity and b) testing over typing (Bruce Eckel wrote an article
> on that, which made a lot of sense to me). At the same time, I'm still
> carrying scars from having a few leaks in the abstractions for a data
> access API I wrote in my previous job...

But these are the things that make us learn. :-)

Kind regards

robert

Einar Høst

3/10/2006 10:38:00 AM

0

Robert Klemme wrote:
> Einar wrote:
>
>>I'm a bit ambivalent on the strictness issue. I buy your arguments for
>>a) simplicity and b) testing over typing (Bruce Eckel wrote an article
>>on that, which made a lot of sense to me). At the same time, I'm still
>>carrying scars from having a few leaks in the abstractions for a data
>>access API I wrote in my previous job...
>
>
> But these are the things that make us learn. :-)
>

Ah, yes, I guess it's like physical exercise - "no pain, no gain"
(suddenly, images of Gwydion from King's Quest III appear in my head) :-)

- Einar

Robert Klemme

3/10/2006 10:50:00 AM

0

Einar Høst wrote:
> Robert Klemme wrote:
>> Einar wrote:
>>
>>> I'm a bit ambivalent on the strictness issue. I buy your arguments
>>> for a) simplicity and b) testing over typing (Bruce Eckel wrote an
>>> article on that, which made a lot of sense to me). At the same
>>> time, I'm still carrying scars from having a few leaks in the
>>> abstractions for a data access API I wrote in my previous job...
>>
>>
>> But these are the things that make us learn. :-)
>>
>
> Ah, yes, I guess it's like physical exercise - "no pain, no gain"
> (suddenly, images of Gwydion from King's Quest III appear in my head)
> :-)

Actually I believe this is how learning works: basically it's trial and
error. If you run into an error, you usually learn something. :-)

robert