Version française
Home     About     Download     Resources     Contact us    
Browse thread
[Caml-list] Unix.kill on Win32
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: William Lovas <wlovas@s...>
Subject: Re: [Caml-list] static class member....
On Wed, Aug 06, 2003 at 11:11:48AM -0700, David Brown wrote:
> On Wed, Aug 06, 2003 at 06:43:30PM +0100, Richard Jones wrote:
> > The question though is why does my example work? Is this a bug
> > in the compiler?
> [...]
> 
> Creating objects of classes is an unusual thing in ocaml, since it is
> like a function application of zero arguments.

Yes, i've just been playing around with it.  It's somewhat instructive to
limit yourself to the core language, and consider instantiation via `new'
to be something like applying a function whose first argument is ().

For a class with no arguments, e.g. something like,

    class foo =
        let counter = ref 0 in
        object
            method next () = incr counter; !counter
        end

the equivalent in the core language might be something like the following
interaction:

    # let new_counter =
        let counter = ref 0 in
        fun () -> fun () -> (incr counter; !counter);;
    val new_counter : unit -> unit -> int = <fun>
    # let count1 = new_counter ();;
    val count1 : unit -> int = <fun>
    # let count2 = new_counter ();;
    val count2 : unit -> int = <fun>
    # count1 ();;
    - : int = 1
    # count2 ();;
    - : int = 2
    # count1 ();;
    - : int = 3

where new_counter's first unit parameter is something like `new'.

But for classes that take arguments, as in

    class foo x =
        let counter = ref 0 in
        object
            method next () = incr counter; !counter
        end

the special initial unit parameter gets lifted up to the top, with the
other argument:

    # let new_counter () x =
        let counter = ref 0 in
        fun () -> (incr counter; !counter);;
    val new_counter : unit -> 'a -> unit -> int = <fun>
    # let count1 = new_counter () "(unused)";;
    val count1 : unit -> int = <fun>
    # let count2 = new_counter () "(unused)";;
    val count2 : unit -> int = <fun>
    # count1 ();;
    - : int = 1
    # count2 ();;
    - : int = 1
    # count1 ();;
    - : int = 2

(Note that the "class parameter" `x' is unused in both examples.)

When translated into this core language representation, it's syntactically
apparent why the counter is local to each "object" in one case and global
to all "objects" in the other -- in the first case, `counter's scope is the
closure that creates new "objects" (which are also closures), while in the
second, it is local to each "object" (each new closure gets its own copy).

Using this knowledge, it's possible to create a class with a parameter that
keeps the counter global to all instances:

    class foo =
        let counter = ref 0 in
        fun x ->
            object
                method next () = incr counter; !counter
            end

Maybe there's a better explanation, but viewed this way, the syntax for
class definitions -- or at least the syntactic sugar -- is somewhat
idiosyncratic.

cheers,
William

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners