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
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
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 G. II
James Edward G. II wrote:
James Edward G. 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 [email protected] writes:
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.
Robert K. wrote:
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!
George O. wrote:
@suit = suit.dup.freeze
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…
Robert K. wrote:
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 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 wrote:
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