Freezing an arbitary object

Discussion in 'Ruby' started by Aryeh M. Frierdman, Jul 6, 2003.

  1. Lets say I am doing design by contract and want to do a call like this:

    test=UnitTest::new

    foo=1
    test.invariant(foo)
    foo+=1 # should produce an error and exit

    in UnitTest::invariant I want something like this (this code doesn't
    work):

    class UnitTest
    ....
    def invariant(aObj)
    aObj.freeze
    end
    ....
    end

    What am I missing, yes I know aObj is a reference thus freezing it does
    freeze the actual param.
    Aryeh M. Frierdman, Jul 6, 2003
    #1
    1. Advertising

  2. "Aryeh M. Frierdman" <>
    > foo=1
    > test.invariant(foo)
    > foo+=1 # should produce an error and exit


    This will work like you want if you make

    foo = [1,2,3]
    test.invariant(foo)
    foo[0] = 2

    Now, with foo = 1 even foo.freeze will not work:

    #-------------------------------------------------------------
    C:\>ruby -ve "foo = 1; foo.freeze; foo = 2; puts foo; "
    ruby 1.8.0 (2003-06-23) [i386-mswin32]
    2

    C:\>ruby -e "foo = [1]; foo.freeze; foo = 2; puts foo; "
    2

    C:\>ruby -e "foo = [1]; foo.freeze; foo[0] = 2; puts foo; "
    -e:1:in `[]=': can't modify frozen array (TypeError)
    from -e:1
    #-------------------------------------------------------------

    HTH,
    -- shanko
    Shashank Date, Jul 6, 2003
    #2
    1. Advertising

  3. On Mon, Jul 07, 2003 at 04:32:50AM +0900, Aryeh M. Frierdman wrote:
    > foo=1
    > test.invariant(foo)
    > foo+=1 # should produce an error and exit


    Local variables are not objects, and you can't freeze them. They contain a
    reference to an object, so you can freeze the object they refer to, but not
    the variable itself.

    In Ruby, Integers are immutable anyway, so 1.freeze is legal but doesn't
    actually do anything.

    But if you use instance variables instead:

    @foo = 1
    freeze # or "self.freeze"
    @foo = 2 # >> TypeError: can't modify frozen object

    Regards,

    Brian.
    Brian Candler, Jul 6, 2003
    #3
  4. Thanks for the answers so far but "none" of them actually do what I want.
    What I want to do is declare some instance/var/whatever as being invariant
    and any attemt to vary it will result in an error. I am convinced their
    has to be some generic way to do this *without* the caller to the "test"
    being "aware" that they are asking for it to be froozen. The int example
    I gave was only that an example it could of very well been a String,
    MyClass, EvilDictator, etc.
    Aryeh M. Frierdman, Jul 6, 2003
    #4
  5. On Mon, Jul 07, 2003 at 06:53:20AM +0900, Aryeh M. Frierdman wrote:
    > Thanks for the answers so far but "none" of them actually do what I want.
    > What I want to do is declare some instance/var/whatever as being invariant


    Well, you should know what you mean by "whatever"

    - local variables: cannot be frozen, since they don't belong to an object
    and are not an object themselves. They can always be reassigned to point
    to another object. Sorry, that's a Ruby fact of life.

    - instance variables: are frozen when the object containing them is frozen

    class Foo
    attr_accessor :x
    end
    a = Foo.new
    a.x = 99
    a.freeze
    a.x = 100 # TypeError: can't modify frozen object

    > and any attemt to vary it will result in an error. I am convinced their
    > has to be some generic way to do this *without* the caller to the "test"
    > being "aware" that they are asking for it to be froozen. The int example
    > I gave was only that an example it could of very well been a String,
    > MyClass, EvilDictator, etc.


    Taking String as an example:

    foo = "hello"
    foo.freeze
    foo << "x" # Error: object referenced by foo is frozen
    foo = "bye" # Not error: foo now references a completely different object

    And it can be done at a distance:

    def my_test_function(x)
    x.freeze
    end

    foo = "a"
    my_test_function(foo)
    foo << "b" # Error: object has been frozen

    But like I say, local variable "foo" cannot be frozen. I hope that's clear
    enough...

    Brian.
    Brian Candler, Jul 6, 2003
    #5
  6. Brian Candler wrote:

    > - local variables: cannot be frozen, since they don't belong to an object
    > and are not an object themselves. They can always be reassigned to point
    > to another object. Sorry, that's a Ruby fact of life.


    I wonder why this doesn't work? I didn't expect it to, but I'm curious.

    irb(main):005:0> b = binding
    #<Binding:0x401d7e7c>
    irb(main):006:0> eval "y=1", b
    1
    irb(main):007:0> eval "y", b
    1
    irb(main):008:0> b.freeze
    #<Binding:0x401d7e7c>
    irb(main):009:0> eval "y=2", b
    2

    Would it be useful to be able to freeze the current binding? Disastrous?
    Inefficient?
    Joel VanderWerf, Jul 6, 2003
    #6
  7. Joel VanderWerf wrote:

    > Brian Candler wrote:
    >
    >> - local variables: cannot be frozen, since they don't belong to an object
    >> and are not an object themselves. They can always be reassigned to
    >> point to another object. Sorry, that's a Ruby fact of life.

    >
    > I wonder why this doesn't work? I didn't expect it to, but I'm curious.
    >
    > irb(main):005:0> b = binding
    > #<Binding:0x401d7e7c>
    > irb(main):006:0> eval "y=1", b
    > 1
    > irb(main):007:0> eval "y", b
    > 1
    > irb(main):008:0> b.freeze
    > #<Binding:0x401d7e7c>
    > irb(main):009:0> eval "y=2", b
    > 2
    >
    > Would it be useful to be able to freeze the current binding? Disastrous?
    > Inefficient?


    Being new to ruby I would not know the exact reasons but I susbect that
    at the interpreter level a local is implimented as a ptr into a stack frame
    vs. a ptr to the free store thus it would be dangerous to freeze a tempurary
    object. On second thought this might not be true since how whould you
    handle doing garbage collection on a long running method that "free's" a
    local????
    Aryeh M. Frierdman, Jul 6, 2003
    #7
  8. Aryeh M. Frierdman

    Aredridel Guest

    Doesn't a constant do what's needed here?

    irb(main):001:0> Foo = 1
    => 1
    irb(main):002:0> Foo = 2
    (irb):2: warning: already initialized constant Foo
    => 2
    irb(main):003:0>

    Ari
    Aredridel, Jul 7, 2003
    #8
  9. "Aryeh M. Frierdman" <> schrieb im Newsbeitrag
    news:0N0Oa.44153$...
    > Thanks for the answers so far but "none" of them actually do what I

    want.
    > What I want to do is declare some instance/var/whatever as being

    invariant
    > and any attemt to vary it will result in an error. I am convinced their
    > has to be some generic way to do this *without* the caller to the "test"
    > being "aware" that they are asking for it to be froozen. The int

    example
    > I gave was only that an example it could of very well been a String,
    > MyClass, EvilDictator, etc.


    Apparently you want two things:

    - freeze an instance
    - make an object reference unchangeable

    It's important to not confuse these two issues. The first is a property
    of an instance while the latter is a property of an object reference. In
    Ruby there are only references. There is no distinction between pointers,
    references and values like one might know from C++. And there's a subtle
    difference between C++ references and Ruby references: C++ references
    can't be changed and always refer to the instance they were initialized
    with, Ruby references can be changed. Thus Ruby references do have a
    little similarity with C++ pointers - but not too much, since pointer
    arithmetic is missing.

    The first is achieved by doing obj.freeze as you determined correctly,
    while the latter is not possible with local references as Brian pointed
    out. The closest you can get is to declare a constant (first letter
    uppercase) and then get a warning on reassignment like in:

    irb(main):001:0> This_is_const = "foo"
    "foo"
    irb(main):002:0> This_is_const.freeze
    "foo"
    irb(main):003:0> This_is_const << "foo"
    TypeError: can't modify frozen string
    from (irb):3:in `<<'
    from (irb):3
    irb(main):004:0> This_is_const = "bar"
    (irb):4: warning: already initialized constant This_is_const
    "bar"
    irb(main):005:0>

    Regards

    robert
    Robert Klemme, Jul 7, 2003
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Kievlan

    ASP.NET freezing

    John Kievlan, Aug 7, 2003, in forum: ASP .Net
    Replies:
    3
    Views:
    1,514
    John Kievlan
    Aug 7, 2003
  2. =?Utf-8?B?U3RldmVuIEs=?=

    IIS / ASP.NET freezing computer

    =?Utf-8?B?U3RldmVuIEs=?=, Mar 13, 2005, in forum: ASP .Net
    Replies:
    6
    Views:
    486
    Alvin Bruney [ASP.NET MVP]
    Mar 22, 2005
  3. John Smith

    Arbitary VTABLE/Python

    John Smith, Apr 15, 2004, in forum: Python
    Replies:
    2
    Views:
    459
    Your name
    May 4, 2004
  4. Aryeh M. Friedman

    Getting an arbitary date the *RIGHT* way

    Aryeh M. Friedman, Jan 21, 2009, in forum: Java
    Replies:
    6
    Views:
    347
    Roedy Green
    Jan 23, 2009
  5. George Vlahakis

    Receiving arbitary 2-dimensional tables in a WebService method

    George Vlahakis, Jun 27, 2006, in forum: ASP .Net Web Services
    Replies:
    1
    Views:
    111
Loading...

Share This Page