[Newbie] Immutable objects

E

Einar Høst

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
 
R

Robert Klemme

Einar said:
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
 
J

James Edward Gray II

Hi,

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

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

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

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

James Edward Gray II=
 
E

Einar

Robert said:
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
 
E

Einar

James said:
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
 
G

George Ogata

Einar said:
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.
 
E

Einar

George said:
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
 
R

Robert Klemme

Einar said:
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
 
E

Einar Høst

Robert said:
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
 
R

Robert Klemme

Einar said:
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
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top