Forum: Ruby Immutable objects

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.
Einar Høst (Guest)
on 2006-03-09 14:25
(Received via mailing list)
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
Robert K. (Guest)
on 2006-03-09 16:40
(Received via mailing list)
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 G. (Guest)
on 2006-03-09 16:52
(Received via mailing list)
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
Einar (Guest)
on 2006-03-09 17:20
(Received via mailing list)
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!

- Einar
Einar (Guest)
on 2006-03-09 17:26
(Received via mailing list)
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
George O. (Guest)
on 2006-03-09 21:34
(Received via mailing list)
Einar <removed_email_address@domain.invalid> 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.
Einar (Guest)
on 2006-03-10 10:41
(Received via mailing list)
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...

- Einar
Robert K. (Guest)
on 2006-03-10 11:20
(Received via mailing list)
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 (Guest)
on 2006-03-10 12:39
(Received via mailing list)
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
Robert K. (Guest)
on 2006-03-10 14:13
(Received via mailing list)
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
This topic is locked and can not be replied to.