caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] namespace inside object?
@ 2017-02-09 20:36 Steffen Smolka
  2017-02-09 22:55 ` Jeremy Yallop
  0 siblings, 1 reply; 12+ messages in thread
From: Steffen Smolka @ 2017-02-09 20:36 UTC (permalink / raw)
  To: caml-list

[-- Attachment #1: Type: text/plain, Size: 521 bytes --]

Is it possible to create namespaces inside an object? Concretely, I would
like to write

class buffer = object(self)
  ...
  method get = ...

  module Latin1 = struct
    method get = ...
  end

  module Utf8 = struct
    method get = ...
  end
end

so that given an object b : buffer, I can call methods
b#get
b#Latin1.get
b#Utf8.get

Declaring modules inside an object seems to be illegal, though. Is there
any way to achieve something along those lines? Is there a better way to
structure things?

Thanks,
-- Steffen

[-- Attachment #2: Type: text/html, Size: 807 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] namespace inside object?
  2017-02-09 20:36 [Caml-list] namespace inside object? Steffen Smolka
@ 2017-02-09 22:55 ` Jeremy Yallop
  2017-02-09 23:19   ` Steffen Smolka
  0 siblings, 1 reply; 12+ messages in thread
From: Jeremy Yallop @ 2017-02-09 22:55 UTC (permalink / raw)
  To: Steffen Smolka; +Cc: Caml List

Dear Steffen,

On 9 February 2017 at 20:36, Steffen Smolka <smolka@cs.cornell.edu> wrote:
> Is it possible to create namespaces inside an object? Concretely, I would
> like to write
>
> class buffer = object(self)
>   ...
>   method get = ...
>
>   module Latin1 = struct
>     method get = ...
>   end
>
>   module Utf8 = struct
>     method get = ...
>   end
> end
>
> so that given an object b : buffer, I can call methods
> b#get
> b#Latin1.get
> b#Utf8.get

It's possible to achieve something like this using methods that return
objects.  If your nested objects don't need to access the internal
state of the parent then you might write it like this:

  class buffer =
    let latin1 = object
      method get = ...
   end
   and utf8 = object
      method get = ...
   end in
   object(self)
     ...
     method get = ...
     method latin1 = latin1
     method utf8 = utf8
   end

With this approach you can write

   b#get
   b#latin1#get
   b#utf8#get

which, apart from some minor orthographic differences, looks like what
you were aiming for.

Your intuition that this isn't really idiomatic OCaml is right,
though.  In OCaml, unlike some other languages with classes and
objects, classes are not usually used as namespaces; method names are
globally (or, rather, "ambiently") scoped, and there's no real support
for the kind of nesting that you're interested in.  Instead, people
typically build nested namespaces using modules:

  module Buffer =
  struct
     let get = ...

     module Latin1 = struct
        let get = ...
     end

     module Utf8 = struct
        let get = ...
     end
  end

With the module approach you write the 'receiver' after the 'method'
rather than before, but that doesn't seem like a huge hardship.  (10%
of the world manages to get by with VSO languages.)

  Buffer.get b ...
  Buffer.Latin1.get b ...
  Buffer.Utf8.get b ...

If you're keen to stick with objects there are slightly more idiomatic
ways to make it work.  You could, of course, replace the '.' with a
'_' and define methods 'latin1_get', 'utf8_get' in place of
'Latin1.get', 'Utf8.get'.  Or you could select the encoding using a
variant type:

  type enc = Latin1 | Utf8

  class buffer =
  object (self)
     method get = function
         | Latin1 -> ...
         | Utf8 -> ...
  end

Of course, the order of the words in an invocation changes again, but
there's no real increase in complexity for the caller:

  b#get Latin1
  b#get Utf8

This last approach can be taken quite far -- for example, you could
enrich the type 'enc' so that the return type of 'get' varies
according to the encoding.

Kind regards,

Jeremy

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] namespace inside object?
  2017-02-09 22:55 ` Jeremy Yallop
@ 2017-02-09 23:19   ` Steffen Smolka
  2017-02-09 23:37     ` Gerd Stolpmann
  0 siblings, 1 reply; 12+ messages in thread
From: Steffen Smolka @ 2017-02-09 23:19 UTC (permalink / raw)
  To: Jeremy Yallop; +Cc: Caml List

[-- Attachment #1: Type: text/plain, Size: 4002 bytes --]

Thanks for the detailed answer, Jeremy!

If you're keen to stick with objects
>

Yes, I rely on inheritance and dynamic dispatch for what I have in mind.
(This is actually the first time I'm touching the dark object oriented side
of OCaml :) )

To give some more context, I am refactoring some code that uses modules and
no objects. The reason I want to move to objects is that I want to derive a
slightly enhanced module from some base implementation. Inheritance +
dynamic dispatch allow me to do so with very little trouble: I can simply
overwrite a few methods from the base implementation.

I suppose I could achieve the same by turning the base module into a
functor, and abstracting over the functions that my enhanced implementation
needs to replace. I think it won't be quite as natural, but I'll give that
a try.

Or you could select the encoding using a variant type:


Good idea, and I'm happy with the syntax for the caller. But I'm more
concerned with the organization of the code; this would mix the Latin1 and
Utf8 implementations. I would rather keep them separate.

-- Steffen


On Thu, Feb 9, 2017 at 5:55 PM, Jeremy Yallop <yallop@gmail.com> wrote:

> Dear Steffen,
>
> On 9 February 2017 at 20:36, Steffen Smolka <smolka@cs.cornell.edu> wrote:
> > Is it possible to create namespaces inside an object? Concretely, I would
> > like to write
> >
> > class buffer = object(self)
> >   ...
> >   method get = ...
> >
> >   module Latin1 = struct
> >     method get = ...
> >   end
> >
> >   module Utf8 = struct
> >     method get = ...
> >   end
> > end
> >
> > so that given an object b : buffer, I can call methods
> > b#get
> > b#Latin1.get
> > b#Utf8.get
>
> It's possible to achieve something like this using methods that return
> objects.  If your nested objects don't need to access the internal
> state of the parent then you might write it like this:
>
>   class buffer =
>     let latin1 = object
>       method get = ...
>    end
>    and utf8 = object
>       method get = ...
>    end in
>    object(self)
>      ...
>      method get = ...
>      method latin1 = latin1
>      method utf8 = utf8
>    end
>
> With this approach you can write
>
>    b#get
>    b#latin1#get
>    b#utf8#get
>
> which, apart from some minor orthographic differences, looks like what
> you were aiming for.
>
> Your intuition that this isn't really idiomatic OCaml is right,
> though.  In OCaml, unlike some other languages with classes and
> objects, classes are not usually used as namespaces; method names are
> globally (or, rather, "ambiently") scoped, and there's no real support
> for the kind of nesting that you're interested in.  Instead, people
> typically build nested namespaces using modules:
>
>   module Buffer =
>   struct
>      let get = ...
>
>      module Latin1 = struct
>         let get = ...
>      end
>
>      module Utf8 = struct
>         let get = ...
>      end
>   end
>
> With the module approach you write the 'receiver' after the 'method'
> rather than before, but that doesn't seem like a huge hardship.  (10%
> of the world manages to get by with VSO languages.)
>
>   Buffer.get b ...
>   Buffer.Latin1.get b ...
>   Buffer.Utf8.get b ...
>
> If you're keen to stick with objects there are slightly more idiomatic
> ways to make it work.  You could, of course, replace the '.' with a
> '_' and define methods 'latin1_get', 'utf8_get' in place of
> 'Latin1.get', 'Utf8.get'.  Or you could select the encoding using a
> variant type:
>
>   type enc = Latin1 | Utf8
>
>   class buffer =
>   object (self)
>      method get = function
>          | Latin1 -> ...
>          | Utf8 -> ...
>   end
>
> Of course, the order of the words in an invocation changes again, but
> there's no real increase in complexity for the caller:
>
>   b#get Latin1
>   b#get Utf8
>
> This last approach can be taken quite far -- for example, you could
> enrich the type 'enc' so that the return type of 'get' varies
> according to the encoding.
>
> Kind regards,
>
> Jeremy
>

[-- Attachment #2: Type: text/html, Size: 5634 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] namespace inside object?
  2017-02-09 23:19   ` Steffen Smolka
@ 2017-02-09 23:37     ` Gerd Stolpmann
  2017-02-09 23:54       ` Steffen Smolka
  0 siblings, 1 reply; 12+ messages in thread
From: Gerd Stolpmann @ 2017-02-09 23:37 UTC (permalink / raw)
  To: Steffen Smolka, Jeremy Yallop; +Cc: Caml List


[-- Attachment #1.1: Type: text/plain, Size: 6451 bytes --]

Am Donnerstag, den 09.02.2017, 18:19 -0500 schrieb Steffen Smolka:
> Thanks for the detailed answer, Jeremy!
> 
> > If you're keen to stick with objects
> Yes, I rely on inheritance and dynamic dispatch for what I have in
> mind. (This is actually the first time I'm touching the dark object
> oriented side of OCaml :) ) 
> 
> To give some more context, I am refactoring some code that uses
> modules and no objects. The reason I want to move to objects is that
> I want to derive a slightly enhanced module from some base
> implementation. Inheritance + dynamic dispatch allow me to do so with
> very little trouble: I can simply overwrite a few methods from the
> base implementation.
> 
> I suppose I could achieve the same by turning the base module into a
> functor, and abstracting over the functions that my enhanced
> implementation needs to replace. I think it won't be quite as
> natural, but I'll give that a try.
First-class modules could also be an option:  Let's assume both the
base module and the modified one can use the same module type:
module T = sig ... end
Now, define the base module like
module Base : T =
   ...
end
then, define the modified one:
module Mod : T =
   include Base
   ... now override what you need to change but note that there's no
dynamic dispatch ...
end
Of course, you could also use functors for making these modules.
Now turn this into first-class modules and pass them around:
let base = (module Base : T)
let mod = (module Mod : T)
The syntax for unpacking the module is quite cumbersome:
let module M = (val base : T) in
M.function ...
Unfortunately, there's nothing simple like base.function.
Compared with objects you get:
 * You can also put types and (to some degree) modules into these "code containers"
 * However, there's no dynamic dispatch except you arrange explicitly for that, e.g. with references to functions
 * Generally, a heavier syntax, but it might be ok
Gerd
> > > Or you could select the encoding using a > > variant type:> > Good idea, and I'm happy with the syntax for the caller. But I'm more concerned with the organization of the code; this would mix the Latin1 and Utf8 implementations. I would rather keep them separate.
> > -- Steffen
>  

> On Thu, Feb 9, 2017 at 5:55 PM, Jeremy Yallop > <yallop@gmail.com>>  wrote:
> > Dear Steffen,
> > 

> > 
> > On 9 February 2017 at 20:36, Steffen Smolka <smolka@cs.cornell.edu> wrote:
> > 
> > > Is it possible to create namespaces inside an object? Concretely, I would
> > 
> > > like to write
> > 
> > >
> > 
> > > class buffer = object(self)
> > 
> > >   ...
> > 
> > >   method get = ...
> > 
> > >
> > 
> > >   module Latin1 = struct
> > 
> > >     method get = ...
> > 
> > >   end
> > 
> > >
> > 
> > >   module Utf8 = struct
> > 
> > >     method get = ...
> > 
> > >   end
> > 
> > > end
> > 
> > >
> > 
> > > so that given an object b : buffer, I can call methods
> > 
> > > b#get
> > 
> > > b#Latin1.get
> > 
> > > b#Utf8.get
> > 

> > 
> > It's possible to achieve something like this using methods that return
> > 
> > objects.  If your nested objects don't need to access the internal
> > 
> > state of the parent then you might write it like this:
> > 

> > 
> >   class buffer =
> > 
> >     let latin1 = object
> > 
> >       method get = ...
> > 
> >    end
> > 
> >    and utf8 = object
> > 
> >       method get = ...
> > 
> >    end in
> > 
> >    object(self)
> > 
> >      ...
> > 
> >      method get = ...
> > 
> >      method latin1 = latin1
> > 
> >      method utf8 = utf8
> > 
> >    end
> > 

> > 
> > With this approach you can write
> > 

> > 
> >    b#get
> > 
> >    b#latin1#get
> > 
> >    b#utf8#get
> > 

> > 
> > which, apart from some minor orthographic differences, looks like what
> > 
> > you were aiming for.
> > 

> > 
> > Your intuition that this isn't really idiomatic OCaml is right,
> > 
> > though.  In OCaml, unlike some other languages with classes and
> > 
> > objects, classes are not usually used as namespaces; method names are
> > 
> > globally (or, rather, "ambiently") scoped, and there's no real support
> > 
> > for the kind of nesting that you're interested in.  Instead, people
> > 
> > typically build nested namespaces using modules:
> > 

> > 
> >   module Buffer =
> > 
> >   struct
> > 
> >      let get = ...
> > 

> > 
> >      module Latin1 = struct
> > 
> >         let get = ...
> > 
> >      end
> > 

> > 
> >      module Utf8 = struct
> > 
> >         let get = ...
> > 
> >      end
> > 
> >   end
> > 

> > 
> > With the module approach you write the 'receiver' after the 'method'
> > 
> > rather than before, but that doesn't seem like a huge hardship.  (10%
> > 
> > of the world manages to get by with VSO languages.)
> > 

> > 
> >   Buffer.get b ...
> > 
> >   Buffer.Latin1.get b ...
> > 
> >   Buffer.Utf8.get b ...
> > 

> > 
> > If you're keen to stick with objects there are slightly more idiomatic
> > 
> > ways to make it work.  You could, of course, replace the '.' with a
> > 
> > '_' and define methods 'latin1_get', 'utf8_get' in place of
> > 
> > 'Latin1.get', 'Utf8.get'.  Or you could select the encoding using a
> > 
> > variant type:
> > 

> > 
> >   type enc = Latin1 | Utf8
> > 

> > 
> >   class buffer =
> > 
> >   object (self)
> > 
> >      method get = function
> > 
> >          | Latin1 -> ...
> > 
> >          | Utf8 -> ...
> > 
> >   end
> > 

> > 
> > Of course, the order of the words in an invocation changes again, but
> > 
> > there's no real increase in complexity for the caller:
> > 

> > 
> >   b#get Latin1
> > 
> >   b#get Utf8
> > 

> > 
> > This last approach can be taken quite far -- for example, you could
> > 
> > enrich the type 'enc' so that the return type of 'get' varies
> > 
> > according to the encoding.
> > 

> > 
> > Kind regards,
> > 

> > 
> > Jeremy
> > 


> 

-- 
------------------------------------------------------------
Gerd Stolpmann, Darmstadt, Germany    gerd@gerd-stolpmann.de
My OCaml site:          http://www.camlcity.org
Contact details:        http://www.camlcity.org/contact.html
Company homepage:       http://www.gerd-stolpmann.de
------------------------------------------------------------



[-- Attachment #1.2: Type: text/html, Size: 7804 bytes --]

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] namespace inside object?
  2017-02-09 23:37     ` Gerd Stolpmann
@ 2017-02-09 23:54       ` Steffen Smolka
  2017-02-10  2:01         ` Yaron Minsky
  0 siblings, 1 reply; 12+ messages in thread
From: Steffen Smolka @ 2017-02-09 23:54 UTC (permalink / raw)
  To: Gerd Stolpmann; +Cc: Jeremy Yallop, Caml List

[-- Attachment #1: Type: text/plain, Size: 5826 bytes --]

Yeah, I have seen that there is support for first class modules, that's
pretty cool stuff!
I do need dynamic dispatch, though.

-- Steffen

On Thu, Feb 9, 2017 at 6:37 PM, Gerd Stolpmann <info@gerd-stolpmann.de>
wrote:

> Am Donnerstag, den 09.02.2017, 18:19 -0500 schrieb Steffen Smolka:
>
> Thanks for the detailed answer, Jeremy!
>
> If you're keen to stick with objects
>
>
> Yes, I rely on inheritance and dynamic dispatch for what I have in mind.
> (This is actually the first time I'm touching the dark object oriented side
> of OCaml :) )
>
> To give some more context, I am refactoring some code that uses modules
> and no objects. The reason I want to move to objects is that I want to
> derive a slightly enhanced module from some base implementation.
> Inheritance + dynamic dispatch allow me to do so with very little trouble:
> I can simply overwrite a few methods from the base implementation.
>
> I suppose I could achieve the same by turning the base module into a
> functor, and abstracting over the functions that my enhanced implementation
> needs to replace. I think it won't be quite as natural, but I'll give that
> a try.
>
>
> First-class modules could also be an option:  Let's assume both the base
> module and the modified one can use the same module type:
>
> module T = sig ... end
>
> Now, define the base module like
>
> module Base : T =
>    ...
> end
>
> then, define the modified one:
>
> module Mod : T =
>    include Base
>    ... now override what you need to change but note that there's no
> dynamic dispatch ...
> end
>
> Of course, you could also use functors for making these modules.
>
> Now turn this into first-class modules and pass them around:
>
> let base = (module Base : T)
> let mod = (module Mod : T)
>
> The syntax for unpacking the module is quite cumbersome:
>
> let module M = (val base : T) in
> M.function ...
>
> Unfortunately, there's nothing simple like base.function.
>
> Compared with objects you get:
>
>
>    - You can also put types and (to some degree) modules into these "code
>    containers"
>    - However, there's no dynamic dispatch except you arrange explicitly
>    for that, e.g. with references to functions
>    - Generally, a heavier syntax, but it might be ok
>
>
> Gerd
>
>
>
> Or you could select the encoding using a variant type:
>
>
> Good idea, and I'm happy with the syntax for the caller. But I'm more
> concerned with the organization of the code; this would mix the Latin1 and
> Utf8 implementations. I would rather keep them separate.
>
> -- Steffen
>
>
> On Thu, Feb 9, 2017 at 5:55 PM, Jeremy Yallop <yallop@gmail.com> wrote:
>
> Dear Steffen,
>
> On 9 February 2017 at 20:36, Steffen Smolka <smolka@cs.cornell.edu> wrote:
> > Is it possible to create namespaces inside an object? Concretely, I would
> > like to write
> >
> > class buffer = object(self)
> >   ...
> >   method get = ...
> >
> >   module Latin1 = struct
> >     method get = ...
> >   end
> >
> >   module Utf8 = struct
> >     method get = ...
> >   end
> > end
> >
> > so that given an object b : buffer, I can call methods
> > b#get
> > b#Latin1.get
> > b#Utf8.get
>
> It's possible to achieve something like this using methods that return
> objects.  If your nested objects don't need to access the internal
> state of the parent then you might write it like this:
>
>   class buffer =
>     let latin1 = object
>       method get = ...
>    end
>    and utf8 = object
>       method get = ...
>    end in
>    object(self)
>      ...
>      method get = ...
>      method latin1 = latin1
>      method utf8 = utf8
>    end
>
> With this approach you can write
>
>    b#get
>    b#latin1#get
>    b#utf8#get
>
> which, apart from some minor orthographic differences, looks like what
> you were aiming for.
>
> Your intuition that this isn't really idiomatic OCaml is right,
> though.  In OCaml, unlike some other languages with classes and
> objects, classes are not usually used as namespaces; method names are
> globally (or, rather, "ambiently") scoped, and there's no real support
> for the kind of nesting that you're interested in.  Instead, people
> typically build nested namespaces using modules:
>
>   module Buffer =
>   struct
>      let get = ...
>
>      module Latin1 = struct
>         let get = ...
>      end
>
>      module Utf8 = struct
>         let get = ...
>      end
>   end
>
> With the module approach you write the 'receiver' after the 'method'
> rather than before, but that doesn't seem like a huge hardship.  (10%
> of the world manages to get by with VSO languages.)
>
>   Buffer.get b ...
>   Buffer.Latin1.get b ...
>   Buffer.Utf8.get b ...
>
> If you're keen to stick with objects there are slightly more idiomatic
> ways to make it work.  You could, of course, replace the '.' with a
> '_' and define methods 'latin1_get', 'utf8_get' in place of
> 'Latin1.get', 'Utf8.get'.  Or you could select the encoding using a
> variant type:
>
>   type enc = Latin1 | Utf8
>
>   class buffer =
>   object (self)
>      method get = function
>          | Latin1 -> ...
>          | Utf8 -> ...
>   end
>
> Of course, the order of the words in an invocation changes again, but
> there's no real increase in complexity for the caller:
>
>   b#get Latin1
>   b#get Utf8
>
> This last approach can be taken quite far -- for example, you could
> enrich the type 'enc' so that the return type of 'get' varies
> according to the encoding.
>
> Kind regards,
>
> Jeremy
>
>
> --
> ------------------------------------------------------------
> Gerd Stolpmann, Darmstadt, Germany    gerd@gerd-stolpmann.de
> My OCaml site:          http://www.camlcity.org
> Contact details:        http://www.camlcity.org/contact.html
> Company homepage:       http://www.gerd-stolpmann.de
> ------------------------------------------------------------
>
>
>

[-- Attachment #2: Type: text/html, Size: 8374 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] namespace inside object?
  2017-02-09 23:54       ` Steffen Smolka
@ 2017-02-10  2:01         ` Yaron Minsky
  2017-02-10  3:16           ` Steffen Smolka
  0 siblings, 1 reply; 12+ messages in thread
From: Yaron Minsky @ 2017-02-10  2:01 UTC (permalink / raw)
  To: Steffen Smolka; +Cc: Gerd Stolpmann, Jeremy Yallop, Caml List

I've always been a bit confused about what the term "dynamic dispatch"
means, but don't first class modules provide what you want? After all,
when you write:

let f (module M : S) x =
    M.g x

the specific function M.g is determined dynamically, depending on
which first class module is passed into f.

y

On Thu, Feb 9, 2017 at 6:54 PM, Steffen Smolka <smolka@cs.cornell.edu> wrote:
> Yeah, I have seen that there is support for first class modules, that's
> pretty cool stuff!
> I do need dynamic dispatch, though.
>
> -- Steffen
>
> On Thu, Feb 9, 2017 at 6:37 PM, Gerd Stolpmann <info@gerd-stolpmann.de>
> wrote:
>>
>> Am Donnerstag, den 09.02.2017, 18:19 -0500 schrieb Steffen Smolka:
>>
>> Thanks for the detailed answer, Jeremy!
>>
>> If you're keen to stick with objects
>>
>>
>> Yes, I rely on inheritance and dynamic dispatch for what I have in mind.
>> (This is actually the first time I'm touching the dark object oriented side
>> of OCaml :) )
>>
>> To give some more context, I am refactoring some code that uses modules
>> and no objects. The reason I want to move to objects is that I want to
>> derive a slightly enhanced module from some base implementation. Inheritance
>> + dynamic dispatch allow me to do so with very little trouble: I can simply
>> overwrite a few methods from the base implementation.
>>
>> I suppose I could achieve the same by turning the base module into a
>> functor, and abstracting over the functions that my enhanced implementation
>> needs to replace. I think it won't be quite as natural, but I'll give that a
>> try.
>>
>>
>> First-class modules could also be an option:  Let's assume both the base
>> module and the modified one can use the same module type:
>>
>> module T = sig ... end
>>
>> Now, define the base module like
>>
>> module Base : T =
>>    ...
>> end
>>
>> then, define the modified one:
>>
>> module Mod : T =
>>    include Base
>>    ... now override what you need to change but note that there's no
>> dynamic dispatch ...
>> end
>>
>> Of course, you could also use functors for making these modules.
>>
>> Now turn this into first-class modules and pass them around:
>>
>> let base = (module Base : T)
>> let mod = (module Mod : T)
>>
>> The syntax for unpacking the module is quite cumbersome:
>>
>> let module M = (val base : T) in
>> M.function ...
>>
>> Unfortunately, there's nothing simple like base.function.
>>
>> Compared with objects you get:
>>
>> You can also put types and (to some degree) modules into these "code
>> containers"
>> However, there's no dynamic dispatch except you arrange explicitly for
>> that, e.g. with references to functions
>> Generally, a heavier syntax, but it might be ok
>>
>>
>> Gerd
>>
>>
>>
>> Or you could select the encoding using a variant type:
>>
>>
>> Good idea, and I'm happy with the syntax for the caller. But I'm more
>> concerned with the organization of the code; this would mix the Latin1 and
>> Utf8 implementations. I would rather keep them separate.
>>
>> -- Steffen
>>
>>
>> On Thu, Feb 9, 2017 at 5:55 PM, Jeremy Yallop <yallop@gmail.com> wrote:
>>
>> Dear Steffen,
>>
>> On 9 February 2017 at 20:36, Steffen Smolka <smolka@cs.cornell.edu> wrote:
>> > Is it possible to create namespaces inside an object? Concretely, I
>> > would
>> > like to write
>> >
>> > class buffer = object(self)
>> >   ...
>> >   method get = ...
>> >
>> >   module Latin1 = struct
>> >     method get = ...
>> >   end
>> >
>> >   module Utf8 = struct
>> >     method get = ...
>> >   end
>> > end
>> >
>> > so that given an object b : buffer, I can call methods
>> > b#get
>> > b#Latin1.get
>> > b#Utf8.get
>>
>> It's possible to achieve something like this using methods that return
>> objects.  If your nested objects don't need to access the internal
>> state of the parent then you might write it like this:
>>
>>   class buffer =
>>     let latin1 = object
>>       method get = ...
>>    end
>>    and utf8 = object
>>       method get = ...
>>    end in
>>    object(self)
>>      ...
>>      method get = ...
>>      method latin1 = latin1
>>      method utf8 = utf8
>>    end
>>
>> With this approach you can write
>>
>>    b#get
>>    b#latin1#get
>>    b#utf8#get
>>
>> which, apart from some minor orthographic differences, looks like what
>> you were aiming for.
>>
>> Your intuition that this isn't really idiomatic OCaml is right,
>> though.  In OCaml, unlike some other languages with classes and
>> objects, classes are not usually used as namespaces; method names are
>> globally (or, rather, "ambiently") scoped, and there's no real support
>> for the kind of nesting that you're interested in.  Instead, people
>> typically build nested namespaces using modules:
>>
>>   module Buffer =
>>   struct
>>      let get = ...
>>
>>      module Latin1 = struct
>>         let get = ...
>>      end
>>
>>      module Utf8 = struct
>>         let get = ...
>>      end
>>   end
>>
>> With the module approach you write the 'receiver' after the 'method'
>> rather than before, but that doesn't seem like a huge hardship.  (10%
>> of the world manages to get by with VSO languages.)
>>
>>   Buffer.get b ...
>>   Buffer.Latin1.get b ...
>>   Buffer.Utf8.get b ...
>>
>> If you're keen to stick with objects there are slightly more idiomatic
>> ways to make it work.  You could, of course, replace the '.' with a
>> '_' and define methods 'latin1_get', 'utf8_get' in place of
>> 'Latin1.get', 'Utf8.get'.  Or you could select the encoding using a
>> variant type:
>>
>>   type enc = Latin1 | Utf8
>>
>>   class buffer =
>>   object (self)
>>      method get = function
>>          | Latin1 -> ...
>>          | Utf8 -> ...
>>   end
>>
>> Of course, the order of the words in an invocation changes again, but
>> there's no real increase in complexity for the caller:
>>
>>   b#get Latin1
>>   b#get Utf8
>>
>> This last approach can be taken quite far -- for example, you could
>> enrich the type 'enc' so that the return type of 'get' varies
>> according to the encoding.
>>
>> Kind regards,
>>
>> Jeremy
>>
>>
>> --
>> ------------------------------------------------------------
>> Gerd Stolpmann, Darmstadt, Germany    gerd@gerd-stolpmann.de
>> My OCaml site:          http://www.camlcity.org
>> Contact details:        http://www.camlcity.org/contact.html
>> Company homepage:       http://www.gerd-stolpmann.de
>> ------------------------------------------------------------
>>
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] namespace inside object?
  2017-02-10  2:01         ` Yaron Minsky
@ 2017-02-10  3:16           ` Steffen Smolka
  2017-02-10  3:32             ` Yaron Minsky
  2017-02-10  9:38             ` Leo White
  0 siblings, 2 replies; 12+ messages in thread
From: Steffen Smolka @ 2017-02-10  3:16 UTC (permalink / raw)
  To: Yaron Minsky; +Cc: Gerd Stolpmann, Jeremy Yallop, Caml List

[-- Attachment #1: Type: text/plain, Size: 7852 bytes --]

Right....but you have to explicitly make that choice when you implement
`f`. With objects on the other hand, somebody may write a base
implementation c:

class c = object(this)
  method foo = ... this#bar ...
  method bar = ... this#foo ...  (* original definition *)
end

Later on, somebody else may refine this implementation by overwriting c#bar:

class c2 = object(this)
  inherit c
  method bar = ... (* new definition *)
end

Now c2#foo will invoke the new definition of bar, even though the author of
`c` may have never anticipated this (and did not have to account for this
possibility when he defined foo).

So, I would say "dynamic dispatch" plus inheritance give you the ability to
extend modules in ways that weren't necessarily anticipated by the original
author of the module. And yet all the code written by the original author
will work with your extended version of the module.

-- Steffen



On Thu, Feb 9, 2017 at 9:01 PM, Yaron Minsky <yminsky@janestreet.com> wrote:

> I've always been a bit confused about what the term "dynamic dispatch"
> means, but don't first class modules provide what you want? After all,
> when you write:
>
> let f (module M : S) x =
>     M.g x
>
> the specific function M.g is determined dynamically, depending on
> which first class module is passed into f.
>
> y
>
> On Thu, Feb 9, 2017 at 6:54 PM, Steffen Smolka <smolka@cs.cornell.edu>
> wrote:
> > Yeah, I have seen that there is support for first class modules, that's
> > pretty cool stuff!
> > I do need dynamic dispatch, though.
> >
> > -- Steffen
> >
> > On Thu, Feb 9, 2017 at 6:37 PM, Gerd Stolpmann <info@gerd-stolpmann.de>
> > wrote:
> >>
> >> Am Donnerstag, den 09.02.2017, 18:19 -0500 schrieb Steffen Smolka:
> >>
> >> Thanks for the detailed answer, Jeremy!
> >>
> >> If you're keen to stick with objects
> >>
> >>
> >> Yes, I rely on inheritance and dynamic dispatch for what I have in mind.
> >> (This is actually the first time I'm touching the dark object oriented
> side
> >> of OCaml :) )
> >>
> >> To give some more context, I am refactoring some code that uses modules
> >> and no objects. The reason I want to move to objects is that I want to
> >> derive a slightly enhanced module from some base implementation.
> Inheritance
> >> + dynamic dispatch allow me to do so with very little trouble: I can
> simply
> >> overwrite a few methods from the base implementation.
> >>
> >> I suppose I could achieve the same by turning the base module into a
> >> functor, and abstracting over the functions that my enhanced
> implementation
> >> needs to replace. I think it won't be quite as natural, but I'll give
> that a
> >> try.
> >>
> >>
> >> First-class modules could also be an option:  Let's assume both the base
> >> module and the modified one can use the same module type:
> >>
> >> module T = sig ... end
> >>
> >> Now, define the base module like
> >>
> >> module Base : T =
> >>    ...
> >> end
> >>
> >> then, define the modified one:
> >>
> >> module Mod : T =
> >>    include Base
> >>    ... now override what you need to change but note that there's no
> >> dynamic dispatch ...
> >> end
> >>
> >> Of course, you could also use functors for making these modules.
> >>
> >> Now turn this into first-class modules and pass them around:
> >>
> >> let base = (module Base : T)
> >> let mod = (module Mod : T)
> >>
> >> The syntax for unpacking the module is quite cumbersome:
> >>
> >> let module M = (val base : T) in
> >> M.function ...
> >>
> >> Unfortunately, there's nothing simple like base.function.
> >>
> >> Compared with objects you get:
> >>
> >> You can also put types and (to some degree) modules into these "code
> >> containers"
> >> However, there's no dynamic dispatch except you arrange explicitly for
> >> that, e.g. with references to functions
> >> Generally, a heavier syntax, but it might be ok
> >>
> >>
> >> Gerd
> >>
> >>
> >>
> >> Or you could select the encoding using a variant type:
> >>
> >>
> >> Good idea, and I'm happy with the syntax for the caller. But I'm more
> >> concerned with the organization of the code; this would mix the Latin1
> and
> >> Utf8 implementations. I would rather keep them separate.
> >>
> >> -- Steffen
> >>
> >>
> >> On Thu, Feb 9, 2017 at 5:55 PM, Jeremy Yallop <yallop@gmail.com> wrote:
> >>
> >> Dear Steffen,
> >>
> >> On 9 February 2017 at 20:36, Steffen Smolka <smolka@cs.cornell.edu>
> wrote:
> >> > Is it possible to create namespaces inside an object? Concretely, I
> >> > would
> >> > like to write
> >> >
> >> > class buffer = object(self)
> >> >   ...
> >> >   method get = ...
> >> >
> >> >   module Latin1 = struct
> >> >     method get = ...
> >> >   end
> >> >
> >> >   module Utf8 = struct
> >> >     method get = ...
> >> >   end
> >> > end
> >> >
> >> > so that given an object b : buffer, I can call methods
> >> > b#get
> >> > b#Latin1.get
> >> > b#Utf8.get
> >>
> >> It's possible to achieve something like this using methods that return
> >> objects.  If your nested objects don't need to access the internal
> >> state of the parent then you might write it like this:
> >>
> >>   class buffer =
> >>     let latin1 = object
> >>       method get = ...
> >>    end
> >>    and utf8 = object
> >>       method get = ...
> >>    end in
> >>    object(self)
> >>      ...
> >>      method get = ...
> >>      method latin1 = latin1
> >>      method utf8 = utf8
> >>    end
> >>
> >> With this approach you can write
> >>
> >>    b#get
> >>    b#latin1#get
> >>    b#utf8#get
> >>
> >> which, apart from some minor orthographic differences, looks like what
> >> you were aiming for.
> >>
> >> Your intuition that this isn't really idiomatic OCaml is right,
> >> though.  In OCaml, unlike some other languages with classes and
> >> objects, classes are not usually used as namespaces; method names are
> >> globally (or, rather, "ambiently") scoped, and there's no real support
> >> for the kind of nesting that you're interested in.  Instead, people
> >> typically build nested namespaces using modules:
> >>
> >>   module Buffer =
> >>   struct
> >>      let get = ...
> >>
> >>      module Latin1 = struct
> >>         let get = ...
> >>      end
> >>
> >>      module Utf8 = struct
> >>         let get = ...
> >>      end
> >>   end
> >>
> >> With the module approach you write the 'receiver' after the 'method'
> >> rather than before, but that doesn't seem like a huge hardship.  (10%
> >> of the world manages to get by with VSO languages.)
> >>
> >>   Buffer.get b ...
> >>   Buffer.Latin1.get b ...
> >>   Buffer.Utf8.get b ...
> >>
> >> If you're keen to stick with objects there are slightly more idiomatic
> >> ways to make it work.  You could, of course, replace the '.' with a
> >> '_' and define methods 'latin1_get', 'utf8_get' in place of
> >> 'Latin1.get', 'Utf8.get'.  Or you could select the encoding using a
> >> variant type:
> >>
> >>   type enc = Latin1 | Utf8
> >>
> >>   class buffer =
> >>   object (self)
> >>      method get = function
> >>          | Latin1 -> ...
> >>          | Utf8 -> ...
> >>   end
> >>
> >> Of course, the order of the words in an invocation changes again, but
> >> there's no real increase in complexity for the caller:
> >>
> >>   b#get Latin1
> >>   b#get Utf8
> >>
> >> This last approach can be taken quite far -- for example, you could
> >> enrich the type 'enc' so that the return type of 'get' varies
> >> according to the encoding.
> >>
> >> Kind regards,
> >>
> >> Jeremy
> >>
> >>
> >> --
> >> ------------------------------------------------------------
> >> Gerd Stolpmann, Darmstadt, Germany    gerd@gerd-stolpmann.de
> >> My OCaml site:          http://www.camlcity.org
> >> Contact details:        http://www.camlcity.org/contact.html
> >> Company homepage:       http://www.gerd-stolpmann.de
> >> ------------------------------------------------------------
> >>
> >
>

[-- Attachment #2: Type: text/html, Size: 11284 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] namespace inside object?
  2017-02-10  3:16           ` Steffen Smolka
@ 2017-02-10  3:32             ` Yaron Minsky
  2017-02-10  9:38             ` Leo White
  1 sibling, 0 replies; 12+ messages in thread
From: Yaron Minsky @ 2017-02-10  3:32 UTC (permalink / raw)
  To: Steffen Smolka; +Cc: Gerd Stolpmann, Jeremy Yallop, Caml List

Sure. And if that's what you want, objects seem like the right solution.

That said, I find this style hard to think about, since it involves
breaking ordinary notions of abstraction. The more explicit style
where you use functors (or functions, if using first class modules) to
parameterize code feels cleaner and easier to reason about to, though
it does have some more syntactic overhead.

y

On Thu, Feb 9, 2017 at 10:16 PM, Steffen Smolka <smolka@cs.cornell.edu> wrote:
> Right....but you have to explicitly make that choice when you implement `f`.
> With objects on the other hand, somebody may write a base implementation c:
>
> class c = object(this)
>   method foo = ... this#bar ...
>   method bar = ... this#foo ...  (* original definition *)
> end
>
> Later on, somebody else may refine this implementation by overwriting c#bar:
>
> class c2 = object(this)
>   inherit c
>   method bar = ... (* new definition *)
> end
>
> Now c2#foo will invoke the new definition of bar, even though the author of
> `c` may have never anticipated this (and did not have to account for this
> possibility when he defined foo).
>
> So, I would say "dynamic dispatch" plus inheritance give you the ability to
> extend modules in ways that weren't necessarily anticipated by the original
> author of the module. And yet all the code written by the original author
> will work with your extended version of the module.
>
> -- Steffen
>
>
>
> On Thu, Feb 9, 2017 at 9:01 PM, Yaron Minsky <yminsky@janestreet.com> wrote:
>>
>> I've always been a bit confused about what the term "dynamic dispatch"
>> means, but don't first class modules provide what you want? After all,
>> when you write:
>>
>> let f (module M : S) x =
>>     M.g x
>>
>> the specific function M.g is determined dynamically, depending on
>> which first class module is passed into f.
>>
>> y
>>
>> On Thu, Feb 9, 2017 at 6:54 PM, Steffen Smolka <smolka@cs.cornell.edu>
>> wrote:
>> > Yeah, I have seen that there is support for first class modules, that's
>> > pretty cool stuff!
>> > I do need dynamic dispatch, though.
>> >
>> > -- Steffen
>> >
>> > On Thu, Feb 9, 2017 at 6:37 PM, Gerd Stolpmann <info@gerd-stolpmann.de>
>> > wrote:
>> >>
>> >> Am Donnerstag, den 09.02.2017, 18:19 -0500 schrieb Steffen Smolka:
>> >>
>> >> Thanks for the detailed answer, Jeremy!
>> >>
>> >> If you're keen to stick with objects
>> >>
>> >>
>> >> Yes, I rely on inheritance and dynamic dispatch for what I have in
>> >> mind.
>> >> (This is actually the first time I'm touching the dark object oriented
>> >> side
>> >> of OCaml :) )
>> >>
>> >> To give some more context, I am refactoring some code that uses modules
>> >> and no objects. The reason I want to move to objects is that I want to
>> >> derive a slightly enhanced module from some base implementation.
>> >> Inheritance
>> >> + dynamic dispatch allow me to do so with very little trouble: I can
>> >> simply
>> >> overwrite a few methods from the base implementation.
>> >>
>> >> I suppose I could achieve the same by turning the base module into a
>> >> functor, and abstracting over the functions that my enhanced
>> >> implementation
>> >> needs to replace. I think it won't be quite as natural, but I'll give
>> >> that a
>> >> try.
>> >>
>> >>
>> >> First-class modules could also be an option:  Let's assume both the
>> >> base
>> >> module and the modified one can use the same module type:
>> >>
>> >> module T = sig ... end
>> >>
>> >> Now, define the base module like
>> >>
>> >> module Base : T =
>> >>    ...
>> >> end
>> >>
>> >> then, define the modified one:
>> >>
>> >> module Mod : T =
>> >>    include Base
>> >>    ... now override what you need to change but note that there's no
>> >> dynamic dispatch ...
>> >> end
>> >>
>> >> Of course, you could also use functors for making these modules.
>> >>
>> >> Now turn this into first-class modules and pass them around:
>> >>
>> >> let base = (module Base : T)
>> >> let mod = (module Mod : T)
>> >>
>> >> The syntax for unpacking the module is quite cumbersome:
>> >>
>> >> let module M = (val base : T) in
>> >> M.function ...
>> >>
>> >> Unfortunately, there's nothing simple like base.function.
>> >>
>> >> Compared with objects you get:
>> >>
>> >> You can also put types and (to some degree) modules into these "code
>> >> containers"
>> >> However, there's no dynamic dispatch except you arrange explicitly for
>> >> that, e.g. with references to functions
>> >> Generally, a heavier syntax, but it might be ok
>> >>
>> >>
>> >> Gerd
>> >>
>> >>
>> >>
>> >> Or you could select the encoding using a variant type:
>> >>
>> >>
>> >> Good idea, and I'm happy with the syntax for the caller. But I'm more
>> >> concerned with the organization of the code; this would mix the Latin1
>> >> and
>> >> Utf8 implementations. I would rather keep them separate.
>> >>
>> >> -- Steffen
>> >>
>> >>
>> >> On Thu, Feb 9, 2017 at 5:55 PM, Jeremy Yallop <yallop@gmail.com> wrote:
>> >>
>> >> Dear Steffen,
>> >>
>> >> On 9 February 2017 at 20:36, Steffen Smolka <smolka@cs.cornell.edu>
>> >> wrote:
>> >> > Is it possible to create namespaces inside an object? Concretely, I
>> >> > would
>> >> > like to write
>> >> >
>> >> > class buffer = object(self)
>> >> >   ...
>> >> >   method get = ...
>> >> >
>> >> >   module Latin1 = struct
>> >> >     method get = ...
>> >> >   end
>> >> >
>> >> >   module Utf8 = struct
>> >> >     method get = ...
>> >> >   end
>> >> > end
>> >> >
>> >> > so that given an object b : buffer, I can call methods
>> >> > b#get
>> >> > b#Latin1.get
>> >> > b#Utf8.get
>> >>
>> >> It's possible to achieve something like this using methods that return
>> >> objects.  If your nested objects don't need to access the internal
>> >> state of the parent then you might write it like this:
>> >>
>> >>   class buffer =
>> >>     let latin1 = object
>> >>       method get = ...
>> >>    end
>> >>    and utf8 = object
>> >>       method get = ...
>> >>    end in
>> >>    object(self)
>> >>      ...
>> >>      method get = ...
>> >>      method latin1 = latin1
>> >>      method utf8 = utf8
>> >>    end
>> >>
>> >> With this approach you can write
>> >>
>> >>    b#get
>> >>    b#latin1#get
>> >>    b#utf8#get
>> >>
>> >> which, apart from some minor orthographic differences, looks like what
>> >> you were aiming for.
>> >>
>> >> Your intuition that this isn't really idiomatic OCaml is right,
>> >> though.  In OCaml, unlike some other languages with classes and
>> >> objects, classes are not usually used as namespaces; method names are
>> >> globally (or, rather, "ambiently") scoped, and there's no real support
>> >> for the kind of nesting that you're interested in.  Instead, people
>> >> typically build nested namespaces using modules:
>> >>
>> >>   module Buffer =
>> >>   struct
>> >>      let get = ...
>> >>
>> >>      module Latin1 = struct
>> >>         let get = ...
>> >>      end
>> >>
>> >>      module Utf8 = struct
>> >>         let get = ...
>> >>      end
>> >>   end
>> >>
>> >> With the module approach you write the 'receiver' after the 'method'
>> >> rather than before, but that doesn't seem like a huge hardship.  (10%
>> >> of the world manages to get by with VSO languages.)
>> >>
>> >>   Buffer.get b ...
>> >>   Buffer.Latin1.get b ...
>> >>   Buffer.Utf8.get b ...
>> >>
>> >> If you're keen to stick with objects there are slightly more idiomatic
>> >> ways to make it work.  You could, of course, replace the '.' with a
>> >> '_' and define methods 'latin1_get', 'utf8_get' in place of
>> >> 'Latin1.get', 'Utf8.get'.  Or you could select the encoding using a
>> >> variant type:
>> >>
>> >>   type enc = Latin1 | Utf8
>> >>
>> >>   class buffer =
>> >>   object (self)
>> >>      method get = function
>> >>          | Latin1 -> ...
>> >>          | Utf8 -> ...
>> >>   end
>> >>
>> >> Of course, the order of the words in an invocation changes again, but
>> >> there's no real increase in complexity for the caller:
>> >>
>> >>   b#get Latin1
>> >>   b#get Utf8
>> >>
>> >> This last approach can be taken quite far -- for example, you could
>> >> enrich the type 'enc' so that the return type of 'get' varies
>> >> according to the encoding.
>> >>
>> >> Kind regards,
>> >>
>> >> Jeremy
>> >>
>> >>
>> >> --
>> >> ------------------------------------------------------------
>> >> Gerd Stolpmann, Darmstadt, Germany    gerd@gerd-stolpmann.de
>> >> My OCaml site:          http://www.camlcity.org
>> >> Contact details:        http://www.camlcity.org/contact.html
>> >> Company homepage:       http://www.gerd-stolpmann.de
>> >> ------------------------------------------------------------
>> >>
>> >
>
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] namespace inside object?
  2017-02-10  3:16           ` Steffen Smolka
  2017-02-10  3:32             ` Yaron Minsky
@ 2017-02-10  9:38             ` Leo White
  2017-02-10 14:40               ` Evgeny Roubinchtein
  1 sibling, 1 reply; 12+ messages in thread
From: Leo White @ 2017-02-10  9:38 UTC (permalink / raw)
  To: caml-list

[-- Attachment #1: Type: text/plain, Size: 9224 bytes --]

I think it would be more correct to say that you want open recursion.
Classes are the easiest way to get that in OCaml, and they indeed use
dynamic dispatch and inheritance, but there are other mechanisms that
provide open recursion. For example, most proposals for "mixin modules"
support open recursion but I wouldn't say they use dynamic dispatch.


Regards,



Leo



On Thu, 9 Feb 2017, at 10:16 PM, Steffen Smolka wrote:

> Right....but you have to explicitly make that choice when you
> implement `f`. With objects on the other hand, somebody may write a
> base implementation c:
> 

> class c = object(this)

>   method foo = ... this#bar ...

>   method bar = ... this#foo ...  (* original definition *)

> end

> 

> Later on, somebody else may refine this implementation by
> overwriting c#bar:
> 

> class c2 = object(this)

>   inherit c

>   method bar = ... (* new definition *)

> end

> 

> Now c2#foo will invoke the new definition of bar, even though the
> author of `c` may have never anticipated this (and did not have to
> account for this possibility when he defined foo).
> 

> So, I would say "dynamic dispatch" plus inheritance give you the
> ability to extend modules in ways that weren't necessarily
> anticipated by the original author of the module. And yet all the
> code written by the original author will work with your extended
> version of the module.
> 

> -- Steffen

> 

> 

> 

> On Thu, Feb 9, 2017 at 9:01 PM, Yaron Minsky
> <yminsky@janestreet.com> wrote:
>> I've always been a bit confused about what the term "dynamic
>> dispatch"
>>  means, but don't first class modules provide what you want?
>>  After all,
>>  when you write:

>> 

>>  let f (module M : S) x =

>>      M.g x

>> 

>>  the specific function M.g is determined dynamically, depending on

>>  which first class module is passed into f.

>> 
>>  y

>> 

>> On Thu, Feb 9, 2017 at 6:54 PM, Steffen Smolka
>> <smolka@cs.cornell.edu> wrote:
>>  > Yeah, I have seen that there is support for first class modules,
>>  > that's
>>  > pretty cool stuff!

>>  > I do need dynamic dispatch, though.

>>  >

>>  > -- Steffen

>>  >

>>  > On Thu, Feb 9, 2017 at 6:37 PM, Gerd Stolpmann <info@gerd-
>>  > stolpmann.de>
>>  > wrote:

>>  >>

>>  >> Am Donnerstag, den 09.02.2017, 18:19 -0500 schrieb Steffen
>>  >> Smolka:
>>  >>

>>  >> Thanks for the detailed answer, Jeremy!

>>  >>

>>  >> If you're keen to stick with objects

>>  >>

>>  >>

>>  >> Yes, I rely on inheritance and dynamic dispatch for what I have
>>  >> in mind.
>>  >> (This is actually the first time I'm touching the dark object
>>  >> oriented side
>>  >> of OCaml :) )

>>  >>

>>  >> To give some more context, I am refactoring some code that uses
>>  >> modules
>>  >> and no objects. The reason I want to move to objects is that I
>>  >> want to
>>  >> derive a slightly enhanced module from some base implementation.
>>  >> Inheritance
>>  >> + dynamic dispatch allow me to do so with very little trouble: I
>>  >>   can simply
>>  >> overwrite a few methods from the base implementation.

>>  >>

>>  >> I suppose I could achieve the same by turning the base module
>>  >> into a
>>  >> functor, and abstracting over the functions that my enhanced
>>  >> implementation
>>  >> needs to replace. I think it won't be quite as natural, but I'll
>>  >> give that a
>>  >> try.

>>  >>

>>  >>

>>  >> First-class modules could also be an option:  Let's assume both
>>  >> the base
>>  >> module and the modified one can use the same module type:

>>  >>

>>  >> module T = sig ... end

>>  >>

>>  >> Now, define the base module like

>>  >>

>>  >> module Base : T =

>>  >>    ...

>>  >> end

>>  >>

>>  >> then, define the modified one:

>>  >>

>>  >> module Mod : T =

>>  >>    include Base

>>  >>    ... now override what you need to change but note that there's
>>  >>    no
>>  >> dynamic dispatch ...

>>  >> end

>>  >>

>>  >> Of course, you could also use functors for making these modules.
>>  >>

>>  >> Now turn this into first-class modules and pass them around:

>>  >>

>>  >> let base = (module Base : T)

>>  >> let mod = (module Mod : T)

>>  >>

>>  >> The syntax for unpacking the module is quite cumbersome:

>>  >>

>>  >> let module M = (val base : T) in

>>  >> M.function ...

>>  >>

>>  >> Unfortunately, there's nothing simple like base.function.

>>  >>

>>  >> Compared with objects you get:

>>  >>

>>  >> You can also put types and (to some degree) modules into these
>>  >> "code
>>  >> containers"

>>  >> However, there's no dynamic dispatch except you arrange
>>  >> explicitly for
>>  >> that, e.g. with references to functions

>>  >> Generally, a heavier syntax, but it might be ok

>>  >>

>>  >>

>>  >> Gerd

>>  >>

>>  >>

>>  >>

>>  >> Or you could select the encoding using a variant type:

>>  >>

>>  >>

>>  >> Good idea, and I'm happy with the syntax for the caller. But I'm
>>  >> more
>>  >> concerned with the organization of the code; this would mix the
>>  >> Latin1 and
>>  >> Utf8 implementations. I would rather keep them separate.

>>  >>

>>  >> -- Steffen

>>  >>

>>  >>

>>  >> On Thu, Feb 9, 2017 at 5:55 PM, Jeremy Yallop <yallop@gmail.com>
>>  >> wrote:
>>  >>

>>  >> Dear Steffen,

>>  >>

>>  >> On 9 February 2017 at 20:36, Steffen Smolka
>>  >> <smolka@cs.cornell.edu> wrote:
>>  >> > Is it possible to create namespaces inside an object?
>>  >> > Concretely, I
>>  >> > would

>>  >> > like to write

>>  >> >

>>  >> > class buffer = object(self)

>>  >> >   ...

>>  >> >   method get = ...

>>  >> >

>>  >> >   module Latin1 = struct

>>  >> >     method get = ...

>>  >> >   end

>>  >> >

>>  >> >   module Utf8 = struct

>>  >> >     method get = ...

>>  >> >   end

>>  >> > end

>>  >> >

>>  >> > so that given an object b : buffer, I can call methods

>>  >> > b#get

>>  >> > b#Latin1.get

>>  >> > b#Utf8.get

>>  >>

>>  >> It's possible to achieve something like this using methods that
>>  >> return
>>  >> objects.  If your nested objects don't need to access the
>>  >> internal
>>  >> state of the parent then you might write it like this:

>>  >>

>>  >>   class buffer =

>>  >>     let latin1 = object

>>  >>       method get = ...

>>  >>    end

>>  >>    and utf8 = object

>>  >>       method get = ...

>>  >>    end in

>>  >>    object(self)

>>  >>      ...

>>  >>      method get = ...

>>  >>      method latin1 = latin1

>>  >>      method utf8 = utf8

>>  >>    end

>>  >>

>>  >> With this approach you can write

>>  >>

>>  >>    b#get

>>  >>    b#latin1#get

>>  >>    b#utf8#get

>>  >>

>>  >> which, apart from some minor orthographic differences, looks like
>>  >> what
>>  >> you were aiming for.

>>  >>

>>  >> Your intuition that this isn't really idiomatic OCaml is right,

>>  >> though.  In OCaml, unlike some other languages with classes and

>>  >> objects, classes are not usually used as namespaces; method names
>>  >> are
>>  >> globally (or, rather, "ambiently") scoped, and there's no real
>>  >> support
>>  >> for the kind of nesting that you're interested in.  Instead,
>>  >> people
>>  >> typically build nested namespaces using modules:

>>  >>

>>  >>   module Buffer =

>>  >>   struct

>>  >>      let get = ...

>>  >>

>>  >>      module Latin1 = struct

>>  >>         let get = ...

>>  >>      end

>>  >>

>>  >>      module Utf8 = struct

>>  >>         let get = ...

>>  >>      end

>>  >>   end

>>  >>

>>  >> With the module approach you write the 'receiver' after the
>>  >> 'method'
>>  >> rather than before, but that doesn't seem like a huge hardship.
>>  >> (10%
>>  >> of the world manages to get by with VSO languages.)

>>  >>

>>  >>   Buffer.get b ...

>>  >>   Buffer.Latin1.get b ...

>>  >>   Buffer.Utf8.get b ...

>>  >>

>>  >> If you're keen to stick with objects there are slightly more
>>  >> idiomatic
>>  >> ways to make it work.  You could, of course, replace the '.'
>>  >> with a
>>  >> '_' and define methods 'latin1_get', 'utf8_get' in place of

>>  >> 'Latin1.get', 'Utf8.get'.  Or you could select the encoding
>>  >> using a
>>  >> variant type:

>>  >>

>>  >>   type enc = Latin1 | Utf8

>>  >>

>>  >>   class buffer =

>>  >>   object (self)

>>  >>      method get = function

>>  >>          | Latin1 -> ...

>>  >>          | Utf8 -> ...

>>  >>   end

>>  >>

>>  >> Of course, the order of the words in an invocation changes again,
>>  >> but
>>  >> there's no real increase in complexity for the caller:

>>  >>

>>  >>   b#get Latin1

>>  >>   b#get Utf8

>>  >>

>>  >> This last approach can be taken quite far -- for example, you
>>  >> could
>>  >> enrich the type 'enc' so that the return type of 'get' varies

>>  >> according to the encoding.

>>  >>

>>  >> Kind regards,

>>  >>

>>  >> Jeremy

>>  >>

>>  >>

>>  >> --

>>  >> ------------------------------------------------------------

>>  >> Gerd Stolpmann, Darmstadt, Germany    gerd@gerd-stolpmann.de

>>  >> My OCaml site:          http://www.camlcity.org

>>  >> Contact details:        http://www.camlcity.org/contact.html

>>  >> Company homepage:       http://www.gerd-stolpmann.de

>>  >> ------------------------------------------------------------

>>  >>

>>  >



[-- Attachment #2: Type: text/html, Size: 16212 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] namespace inside object?
  2017-02-10  9:38             ` Leo White
@ 2017-02-10 14:40               ` Evgeny Roubinchtein
  2017-02-10 15:16                 ` Markus Mottl
  2017-02-10 15:49                 ` Leo White
  0 siblings, 2 replies; 12+ messages in thread
From: Evgeny Roubinchtein @ 2017-02-10 14:40 UTC (permalink / raw)
  To: Leo White; +Cc: caml-list

[-- Attachment #1: Type: text/plain, Size: 8633 bytes --]

Apologies in advance for my ignorance, but is there some reference(s) you
could point me to where the notion of "open recursion" is defined?  I am
pretty sure I understand "dynamic dispatch."

-- 
Best,
Zhenya

On Fri, Feb 10, 2017 at 4:38 AM, Leo White <leo@lpw25.net> wrote:

> I think it would be more correct to say that you want open recursion.
> Classes are the easiest way to get that in OCaml, and they indeed use
> dynamic dispatch and inheritance, but there are other mechanisms that
> provide open recursion. For example, most proposals for "mixin modules"
> support open recursion but I wouldn't say they use dynamic dispatch.
>
> Regards,
>
> Leo
>
> On Thu, 9 Feb 2017, at 10:16 PM, Steffen Smolka wrote:
>
> Right....but you have to explicitly make that choice when you implement
> `f`. With objects on the other hand, somebody may write a base
> implementation c:
>
> class c = object(this)
>   method foo = ... this#bar ...
>   method bar = ... this#foo ...  (* original definition *)
> end
>
> Later on, somebody else may refine this implementation by overwriting
> c#bar:
>
> class c2 = object(this)
>   inherit c
>   method bar = ... (* new definition *)
> end
>
> Now c2#foo will invoke the new definition of bar, even though the author
> of `c` may have never anticipated this (and did not have to account for
> this possibility when he defined foo).
>
> So, I would say "dynamic dispatch" plus inheritance give you the ability
> to extend modules in ways that weren't necessarily anticipated by the
> original author of the module. And yet all the code written by the original
> author will work with your extended version of the module.
>
> -- Steffen
>
>
>
> On Thu, Feb 9, 2017 at 9:01 PM, Yaron Minsky <yminsky@janestreet.com>
> wrote:
>
> I've always been a bit confused about what the term "dynamic dispatch"
> means, but don't first class modules provide what you want? After all,
> when you write:
>
> let f (module M : S) x =
>     M.g x
>
> the specific function M.g is determined dynamically, depending on
> which first class module is passed into f.
>
> y
>
> On Thu, Feb 9, 2017 at 6:54 PM, Steffen Smolka <smolka@cs.cornell.edu>
> wrote:
> > Yeah, I have seen that there is support for first class modules, that's
> > pretty cool stuff!
> > I do need dynamic dispatch, though.
> >
> > -- Steffen
> >
> > On Thu, Feb 9, 2017 at 6:37 PM, Gerd Stolpmann <info@gerd-stolpmann.de>
> > wrote:
> >>
> >> Am Donnerstag, den 09.02.2017, 18:19 -0500 schrieb Steffen Smolka:
> >>
> >> Thanks for the detailed answer, Jeremy!
> >>
> >> If you're keen to stick with objects
> >>
> >>
> >> Yes, I rely on inheritance and dynamic dispatch for what I have in mind.
> >> (This is actually the first time I'm touching the dark object oriented
> side
> >> of OCaml :) )
> >>
> >> To give some more context, I am refactoring some code that uses modules
> >> and no objects. The reason I want to move to objects is that I want to
> >> derive a slightly enhanced module from some base implementation.
> Inheritance
> >> + dynamic dispatch allow me to do so with very little trouble: I can
> simply
> >> overwrite a few methods from the base implementation.
> >>
> >> I suppose I could achieve the same by turning the base module into a
> >> functor, and abstracting over the functions that my enhanced
> implementation
> >> needs to replace. I think it won't be quite as natural, but I'll give
> that a
> >> try.
> >>
> >>
> >> First-class modules could also be an option:  Let's assume both the base
> >> module and the modified one can use the same module type:
> >>
> >> module T = sig ... end
> >>
> >> Now, define the base module like
> >>
> >> module Base : T =
> >>    ...
> >> end
> >>
> >> then, define the modified one:
> >>
> >> module Mod : T =
> >>    include Base
> >>    ... now override what you need to change but note that there's no
> >> dynamic dispatch ...
> >> end
> >>
> >> Of course, you could also use functors for making these modules.
> >>
> >> Now turn this into first-class modules and pass them around:
> >>
> >> let base = (module Base : T)
> >> let mod = (module Mod : T)
> >>
> >> The syntax for unpacking the module is quite cumbersome:
> >>
> >> let module M = (val base : T) in
> >> M.function ...
> >>
> >> Unfortunately, there's nothing simple like base.function.
> >>
> >> Compared with objects you get:
> >>
> >> You can also put types and (to some degree) modules into these "code
> >> containers"
> >> However, there's no dynamic dispatch except you arrange explicitly for
> >> that, e.g. with references to functions
> >> Generally, a heavier syntax, but it might be ok
> >>
> >>
> >> Gerd
> >>
> >>
> >>
> >> Or you could select the encoding using a variant type:
> >>
> >>
> >> Good idea, and I'm happy with the syntax for the caller. But I'm more
> >> concerned with the organization of the code; this would mix the Latin1
> and
> >> Utf8 implementations. I would rather keep them separate.
> >>
> >> -- Steffen
> >>
> >>
> >> On Thu, Feb 9, 2017 at 5:55 PM, Jeremy Yallop <yallop@gmail.com> wrote:
> >>
> >> Dear Steffen,
> >>
> >> On 9 February 2017 at 20:36, Steffen Smolka <smolka@cs.cornell.edu>
> wrote:
> >> > Is it possible to create namespaces inside an object? Concretely, I
> >> > would
> >> > like to write
> >> >
> >> > class buffer = object(self)
> >> >   ...
> >> >   method get = ...
> >> >
> >> >   module Latin1 = struct
> >> >     method get = ...
> >> >   end
> >> >
> >> >   module Utf8 = struct
> >> >     method get = ...
> >> >   end
> >> > end
> >> >
> >> > so that given an object b : buffer, I can call methods
> >> > b#get
> >> > b#Latin1.get
> >> > b#Utf8.get
> >>
> >> It's possible to achieve something like this using methods that return
> >> objects.  If your nested objects don't need to access the internal
> >> state of the parent then you might write it like this:
> >>
> >>   class buffer =
> >>     let latin1 = object
> >>       method get = ...
> >>    end
> >>    and utf8 = object
> >>       method get = ...
> >>    end in
> >>    object(self)
> >>      ...
> >>      method get = ...
> >>      method latin1 = latin1
> >>      method utf8 = utf8
> >>    end
> >>
> >> With this approach you can write
> >>
> >>    b#get
> >>    b#latin1#get
> >>    b#utf8#get
> >>
> >> which, apart from some minor orthographic differences, looks like what
> >> you were aiming for.
> >>
> >> Your intuition that this isn't really idiomatic OCaml is right,
> >> though.  In OCaml, unlike some other languages with classes and
> >> objects, classes are not usually used as namespaces; method names are
> >> globally (or, rather, "ambiently") scoped, and there's no real support
> >> for the kind of nesting that you're interested in.  Instead, people
> >> typically build nested namespaces using modules:
> >>
> >>   module Buffer =
> >>   struct
> >>      let get = ...
> >>
> >>      module Latin1 = struct
> >>         let get = ...
> >>      end
> >>
> >>      module Utf8 = struct
> >>         let get = ...
> >>      end
> >>   end
> >>
> >> With the module approach you write the 'receiver' after the 'method'
> >> rather than before, but that doesn't seem like a huge hardship.  (10%
> >> of the world manages to get by with VSO languages.)
> >>
> >>   Buffer.get b ...
> >>   Buffer.Latin1.get b ...
> >>   Buffer.Utf8.get b ...
> >>
> >> If you're keen to stick with objects there are slightly more idiomatic
> >> ways to make it work.  You could, of course, replace the '.' with a
> >> '_' and define methods 'latin1_get', 'utf8_get' in place of
> >> 'Latin1.get', 'Utf8.get'.  Or you could select the encoding using a
> >> variant type:
> >>
> >>   type enc = Latin1 | Utf8
> >>
> >>   class buffer =
> >>   object (self)
> >>      method get = function
> >>          | Latin1 -> ...
> >>          | Utf8 -> ...
> >>   end
> >>
> >> Of course, the order of the words in an invocation changes again, but
> >> there's no real increase in complexity for the caller:
> >>
> >>   b#get Latin1
> >>   b#get Utf8
> >>
> >> This last approach can be taken quite far -- for example, you could
> >> enrich the type 'enc' so that the return type of 'get' varies
> >> according to the encoding.
> >>
> >> Kind regards,
> >>
> >> Jeremy
> >>
> >>
> >> --
> >> ------------------------------------------------------------
> >> Gerd Stolpmann, Darmstadt, Germany    gerd@gerd-stolpmann.de
> >> My OCaml site:          http://www.camlcity.org
> >> Contact details:        http://www.camlcity.org/contact.html
> >> Company homepage:       http://www.gerd-stolpmann.de
> >> ------------------------------------------------------------
> >>
> >
>
>
>

[-- Attachment #2: Type: text/html, Size: 16900 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] namespace inside object?
  2017-02-10 14:40               ` Evgeny Roubinchtein
@ 2017-02-10 15:16                 ` Markus Mottl
  2017-02-10 15:49                 ` Leo White
  1 sibling, 0 replies; 12+ messages in thread
From: Markus Mottl @ 2017-02-10 15:16 UTC (permalink / raw)
  To: Evgeny Roubinchtein; +Cc: Leo White, OCaml List

Lets first see what closed recursion typically looks like:

  type t = Num of int | Add of t * t
  let rec eval = function Num n -> n | Add (x, y) -> eval x + eval y

This type cannot be extended recursively with another operation, say
"Sub" for subtraction, because "Add" only takes arguments of type "t",
i.e. it only permits "Num" and "Add" under itself.

If you want to permit extensibility, you have to "break" the
recursion, leaving it open.  This can be done by introducing a type
variable that captures extensions to the datastructure, and an extra
evaluation function argument to "eval" to deal with the evaluation of
extensions.

Polymorphic variants make implementations of open recursion much more
elegant than regular variants.  You can check out a simple example for
the above problem here:

  https://github.com/mmottl/ocaml-prog-pats/blob/master/extensible_ast/ast.ml

Regards,
Markus

On Fri, Feb 10, 2017 at 9:40 AM, Evgeny Roubinchtein
<zhenya1007@gmail.com> wrote:
> Apologies in advance for my ignorance, but is there some reference(s) you
> could point me to where the notion of "open recursion" is defined?  I am
> pretty sure I understand "dynamic dispatch."
>
> --
> Best,
> Zhenya
>
> On Fri, Feb 10, 2017 at 4:38 AM, Leo White <leo@lpw25.net> wrote:
>>
>> I think it would be more correct to say that you want open recursion.
>> Classes are the easiest way to get that in OCaml, and they indeed use
>> dynamic dispatch and inheritance, but there are other mechanisms that
>> provide open recursion. For example, most proposals for "mixin modules"
>> support open recursion but I wouldn't say they use dynamic dispatch.
>>
>> Regards,
>>
>> Leo
>>
>> On Thu, 9 Feb 2017, at 10:16 PM, Steffen Smolka wrote:
>>
>> Right....but you have to explicitly make that choice when you implement
>> `f`. With objects on the other hand, somebody may write a base
>> implementation c:
>>
>> class c = object(this)
>>   method foo = ... this#bar ...
>>   method bar = ... this#foo ...  (* original definition *)
>> end
>>
>> Later on, somebody else may refine this implementation by overwriting
>> c#bar:
>>
>> class c2 = object(this)
>>   inherit c
>>   method bar = ... (* new definition *)
>> end
>>
>> Now c2#foo will invoke the new definition of bar, even though the author
>> of `c` may have never anticipated this (and did not have to account for this
>> possibility when he defined foo).
>>
>> So, I would say "dynamic dispatch" plus inheritance give you the ability
>> to extend modules in ways that weren't necessarily anticipated by the
>> original author of the module. And yet all the code written by the original
>> author will work with your extended version of the module.
>>
>> -- Steffen
>>
>>
>>
>> On Thu, Feb 9, 2017 at 9:01 PM, Yaron Minsky <yminsky@janestreet.com>
>> wrote:
>>
>> I've always been a bit confused about what the term "dynamic dispatch"
>> means, but don't first class modules provide what you want? After all,
>> when you write:
>>
>> let f (module M : S) x =
>>     M.g x
>>
>> the specific function M.g is determined dynamically, depending on
>> which first class module is passed into f.
>>
>> y
>>
>> On Thu, Feb 9, 2017 at 6:54 PM, Steffen Smolka <smolka@cs.cornell.edu>
>> wrote:
>> > Yeah, I have seen that there is support for first class modules, that's
>> > pretty cool stuff!
>> > I do need dynamic dispatch, though.
>> >
>> > -- Steffen
>> >
>> > On Thu, Feb 9, 2017 at 6:37 PM, Gerd Stolpmann <info@gerd-stolpmann.de>
>> > wrote:
>> >>
>> >> Am Donnerstag, den 09.02.2017, 18:19 -0500 schrieb Steffen Smolka:
>> >>
>> >> Thanks for the detailed answer, Jeremy!
>> >>
>> >> If you're keen to stick with objects
>> >>
>> >>
>> >> Yes, I rely on inheritance and dynamic dispatch for what I have in
>> >> mind.
>> >> (This is actually the first time I'm touching the dark object oriented
>> >> side
>> >> of OCaml :) )
>> >>
>> >> To give some more context, I am refactoring some code that uses modules
>> >> and no objects. The reason I want to move to objects is that I want to
>> >> derive a slightly enhanced module from some base implementation.
>> >> Inheritance
>> >> + dynamic dispatch allow me to do so with very little trouble: I can
>> >> simply
>> >> overwrite a few methods from the base implementation.
>> >>
>> >> I suppose I could achieve the same by turning the base module into a
>> >> functor, and abstracting over the functions that my enhanced
>> >> implementation
>> >> needs to replace. I think it won't be quite as natural, but I'll give
>> >> that a
>> >> try.
>> >>
>> >>
>> >> First-class modules could also be an option:  Let's assume both the
>> >> base
>> >> module and the modified one can use the same module type:
>> >>
>> >> module T = sig ... end
>> >>
>> >> Now, define the base module like
>> >>
>> >> module Base : T =
>> >>    ...
>> >> end
>> >>
>> >> then, define the modified one:
>> >>
>> >> module Mod : T =
>> >>    include Base
>> >>    ... now override what you need to change but note that there's no
>> >> dynamic dispatch ...
>> >> end
>> >>
>> >> Of course, you could also use functors for making these modules.
>> >>
>> >> Now turn this into first-class modules and pass them around:
>> >>
>> >> let base = (module Base : T)
>> >> let mod = (module Mod : T)
>> >>
>> >> The syntax for unpacking the module is quite cumbersome:
>> >>
>> >> let module M = (val base : T) in
>> >> M.function ...
>> >>
>> >> Unfortunately, there's nothing simple like base.function.
>> >>
>> >> Compared with objects you get:
>> >>
>> >> You can also put types and (to some degree) modules into these "code
>> >> containers"
>> >> However, there's no dynamic dispatch except you arrange explicitly for
>> >> that, e.g. with references to functions
>> >> Generally, a heavier syntax, but it might be ok
>> >>
>> >>
>> >> Gerd
>> >>
>> >>
>> >>
>> >> Or you could select the encoding using a variant type:
>> >>
>> >>
>> >> Good idea, and I'm happy with the syntax for the caller. But I'm more
>> >> concerned with the organization of the code; this would mix the Latin1
>> >> and
>> >> Utf8 implementations. I would rather keep them separate.
>> >>
>> >> -- Steffen
>> >>
>> >>
>> >> On Thu, Feb 9, 2017 at 5:55 PM, Jeremy Yallop <yallop@gmail.com> wrote:
>> >>
>> >> Dear Steffen,
>> >>
>> >> On 9 February 2017 at 20:36, Steffen Smolka <smolka@cs.cornell.edu>
>> >> wrote:
>> >> > Is it possible to create namespaces inside an object? Concretely, I
>> >> > would
>> >> > like to write
>> >> >
>> >> > class buffer = object(self)
>> >> >   ...
>> >> >   method get = ...
>> >> >
>> >> >   module Latin1 = struct
>> >> >     method get = ...
>> >> >   end
>> >> >
>> >> >   module Utf8 = struct
>> >> >     method get = ...
>> >> >   end
>> >> > end
>> >> >
>> >> > so that given an object b : buffer, I can call methods
>> >> > b#get
>> >> > b#Latin1.get
>> >> > b#Utf8.get
>> >>
>> >> It's possible to achieve something like this using methods that return
>> >> objects.  If your nested objects don't need to access the internal
>> >> state of the parent then you might write it like this:
>> >>
>> >>   class buffer =
>> >>     let latin1 = object
>> >>       method get = ...
>> >>    end
>> >>    and utf8 = object
>> >>       method get = ...
>> >>    end in
>> >>    object(self)
>> >>      ...
>> >>      method get = ...
>> >>      method latin1 = latin1
>> >>      method utf8 = utf8
>> >>    end
>> >>
>> >> With this approach you can write
>> >>
>> >>    b#get
>> >>    b#latin1#get
>> >>    b#utf8#get
>> >>
>> >> which, apart from some minor orthographic differences, looks like what
>> >> you were aiming for.
>> >>
>> >> Your intuition that this isn't really idiomatic OCaml is right,
>> >> though.  In OCaml, unlike some other languages with classes and
>> >> objects, classes are not usually used as namespaces; method names are
>> >> globally (or, rather, "ambiently") scoped, and there's no real support
>> >> for the kind of nesting that you're interested in.  Instead, people
>> >> typically build nested namespaces using modules:
>> >>
>> >>   module Buffer =
>> >>   struct
>> >>      let get = ...
>> >>
>> >>      module Latin1 = struct
>> >>         let get = ...
>> >>      end
>> >>
>> >>      module Utf8 = struct
>> >>         let get = ...
>> >>      end
>> >>   end
>> >>
>> >> With the module approach you write the 'receiver' after the 'method'
>> >> rather than before, but that doesn't seem like a huge hardship.  (10%
>> >> of the world manages to get by with VSO languages.)
>> >>
>> >>   Buffer.get b ...
>> >>   Buffer.Latin1.get b ...
>> >>   Buffer.Utf8.get b ...
>> >>
>> >> If you're keen to stick with objects there are slightly more idiomatic
>> >> ways to make it work.  You could, of course, replace the '.' with a
>> >> '_' and define methods 'latin1_get', 'utf8_get' in place of
>> >> 'Latin1.get', 'Utf8.get'.  Or you could select the encoding using a
>> >> variant type:
>> >>
>> >>   type enc = Latin1 | Utf8
>> >>
>> >>   class buffer =
>> >>   object (self)
>> >>      method get = function
>> >>          | Latin1 -> ...
>> >>          | Utf8 -> ...
>> >>   end
>> >>
>> >> Of course, the order of the words in an invocation changes again, but
>> >> there's no real increase in complexity for the caller:
>> >>
>> >>   b#get Latin1
>> >>   b#get Utf8
>> >>
>> >> This last approach can be taken quite far -- for example, you could
>> >> enrich the type 'enc' so that the return type of 'get' varies
>> >> according to the encoding.
>> >>
>> >> Kind regards,
>> >>
>> >> Jeremy
>> >>
>> >>
>> >> --
>> >> ------------------------------------------------------------
>> >> Gerd Stolpmann, Darmstadt, Germany    gerd@gerd-stolpmann.de
>> >> My OCaml site:          http://www.camlcity.org
>> >> Contact details:        http://www.camlcity.org/contact.html
>> >> Company homepage:       http://www.gerd-stolpmann.de
>> >> ------------------------------------------------------------
>> >>
>> >
>>
>>
>



-- 
Markus Mottl        http://www.ocaml.info        markus.mottl@gmail.com

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] namespace inside object?
  2017-02-10 14:40               ` Evgeny Roubinchtein
  2017-02-10 15:16                 ` Markus Mottl
@ 2017-02-10 15:49                 ` Leo White
  1 sibling, 0 replies; 12+ messages in thread
From: Leo White @ 2017-02-10 15:49 UTC (permalink / raw)
  To: Evgeny Roubinchtein; +Cc: caml-list

[-- Attachment #1: Type: text/plain, Size: 10161 bytes --]

A google search will probably produce some reasonable definitions, but
for a more precise treatment I think you can look in Chapter 18 of
"Types and Programming Languages".


Regards,



Leo





On Fri, 10 Feb 2017, at 09:40 AM, Evgeny Roubinchtein wrote:

> Apologies in advance for my ignorance, but is there some reference(s)
> you could point me to where the notion of "open recursion" is defined?
> I am pretty sure I understand "dynamic dispatch."
> 

> -- 

> Best,

> Zhenya

> 

> On Fri, Feb 10, 2017 at 4:38 AM, Leo White <leo@lpw25.net> wrote:

>> __

>> I think it would be more correct to say that you want open recursion.
>> Classes are the easiest way to get that in OCaml, and they indeed use
>> dynamic dispatch and inheritance, but there are other mechanisms that
>> provide open recursion. For example, most proposals for "mixin
>> modules" support open recursion but I wouldn't say they use dynamic
>> dispatch.
>> 

>> Regards,

>> 

>> Leo

>> 

>> On Thu, 9 Feb 2017, at 10:16 PM, Steffen Smolka wrote:

>>> Right....but you have to explicitly make that choice when you
>>> implement `f`. With objects on the other hand, somebody may write a
>>> base implementation c:
>>> 

>>> class c = object(this)

>>>   method foo = ... this#bar ...

>>>   method bar = ... this#foo ...  (* original definition *)

>>> end

>>> 

>>> Later on, somebody else may refine this implementation by
>>> overwriting c#bar:
>>> 

>>> class c2 = object(this)

>>>   inherit c

>>>   method bar = ... (* new definition *)

>>> end

>>> 

>>> Now c2#foo will invoke the new definition of bar, even though the
>>> author of `c` may have never anticipated this (and did not have to
>>> account for this possibility when he defined foo).
>>> 

>>> So, I would say "dynamic dispatch" plus inheritance give you the
>>> ability to extend modules in ways that weren't necessarily
>>> anticipated by the original author of the module. And yet all the
>>> code written by the original author will work with your extended
>>> version of the module.
>>> 

>>> -- Steffen

>>> 

>>> 

>>> 

>>> On Thu, Feb 9, 2017 at 9:01 PM, Yaron Minsky
>>> <yminsky@janestreet.com> wrote:
>>>> I've always been a bit confused about what the term "dynamic
>>>> dispatch"
>>>> means, but don't first class modules provide what you want?
>>>> After all,
>>>> when you write:

>>>> 

>>>> let f (module M : S) x =

>>>>     M.g x

>>>> 

>>>> the specific function M.g is determined dynamically, depending on

>>>> which first class module is passed into f.

>>>> 
>>>> y

>>>> 

>>>> On Thu, Feb 9, 2017 at 6:54 PM, Steffen Smolka
>>>> <smolka@cs.cornell.edu> wrote:
>>>> > Yeah, I have seen that there is support for first class modules,
>>>> > that's
>>>> > pretty cool stuff!

>>>> > I do need dynamic dispatch, though.

>>>> >

>>>> > -- Steffen

>>>> >

>>>> > On Thu, Feb 9, 2017 at 6:37 PM, Gerd Stolpmann <info@gerd-
>>>> > stolpmann.de>
>>>> > wrote:

>>>> >>

>>>> >> Am Donnerstag, den 09.02.2017, 18:19 -0500 schrieb Steffen
>>>> >> Smolka:
>>>> >>

>>>> >> Thanks for the detailed answer, Jeremy!

>>>> >>

>>>> >> If you're keen to stick with objects

>>>> >>

>>>> >>

>>>> >> Yes, I rely on inheritance and dynamic dispatch for what I have
>>>> >> in mind.
>>>> >> (This is actually the first time I'm touching the dark object
>>>> >> oriented side
>>>> >> of OCaml :) )

>>>> >>

>>>> >> To give some more context, I am refactoring some code that uses
>>>> >> modules
>>>> >> and no objects. The reason I want to move to objects is that I
>>>> >> want to
>>>> >> derive a slightly enhanced module from some base implementation.
>>>> >> Inheritance
>>>> >> + dynamic dispatch allow me to do so with very little trouble: I
>>>> >>   can simply
>>>> >> overwrite a few methods from the base implementation.

>>>> >>

>>>> >> I suppose I could achieve the same by turning the base module
>>>> >> into a
>>>> >> functor, and abstracting over the functions that my enhanced
>>>> >> implementation
>>>> >> needs to replace. I think it won't be quite as natural, but I'll
>>>> >> give that a
>>>> >> try.

>>>> >>

>>>> >>

>>>> >> First-class modules could also be an option:  Let's assume both
>>>> >> the base
>>>> >> module and the modified one can use the same module type:

>>>> >>

>>>> >> module T = sig ... end

>>>> >>

>>>> >> Now, define the base module like

>>>> >>

>>>> >> module Base : T =

>>>> >>    ...

>>>> >> end

>>>> >>

>>>> >> then, define the modified one:

>>>> >>

>>>> >> module Mod : T =

>>>> >>    include Base

>>>> >>    ... now override what you need to change but note that
>>>> >>    there's no
>>>> >> dynamic dispatch ...

>>>> >> end

>>>> >>

>>>> >> Of course, you could also use functors for making these modules.
>>>> >>

>>>> >> Now turn this into first-class modules and pass them around:

>>>> >>

>>>> >> let base = (module Base : T)

>>>> >> let mod = (module Mod : T)

>>>> >>

>>>> >> The syntax for unpacking the module is quite cumbersome:

>>>> >>

>>>> >> let module M = (val base : T) in

>>>> >> M.function ...

>>>> >>

>>>> >> Unfortunately, there's nothing simple like base.function.

>>>> >>

>>>> >> Compared with objects you get:

>>>> >>

>>>> >> You can also put types and (to some degree) modules into these
>>>> >> "code
>>>> >> containers"

>>>> >> However, there's no dynamic dispatch except you arrange
>>>> >> explicitly for
>>>> >> that, e.g. with references to functions

>>>> >> Generally, a heavier syntax, but it might be ok

>>>> >>

>>>> >>

>>>> >> Gerd

>>>> >>

>>>> >>

>>>> >>

>>>> >> Or you could select the encoding using a variant type:

>>>> >>

>>>> >>

>>>> >> Good idea, and I'm happy with the syntax for the caller. But I'm
>>>> >> more
>>>> >> concerned with the organization of the code; this would mix the
>>>> >> Latin1 and
>>>> >> Utf8 implementations. I would rather keep them separate.

>>>> >>

>>>> >> -- Steffen

>>>> >>

>>>> >>

>>>> >> On Thu, Feb 9, 2017 at 5:55 PM, Jeremy Yallop <yallop@gmail.com>
>>>> >> wrote:
>>>> >>

>>>> >> Dear Steffen,

>>>> >>

>>>> >> On 9 February 2017 at 20:36, Steffen Smolka
>>>> >> <smolka@cs.cornell.edu> wrote:
>>>> >> > Is it possible to create namespaces inside an object?
>>>> >> > Concretely, I
>>>> >> > would

>>>> >> > like to write

>>>> >> >

>>>> >> > class buffer = object(self)

>>>> >> >   ...

>>>> >> >   method get = ...

>>>> >> >

>>>> >> >   module Latin1 = struct

>>>> >> >     method get = ...

>>>> >> >   end

>>>> >> >

>>>> >> >   module Utf8 = struct

>>>> >> >     method get = ...

>>>> >> >   end

>>>> >> > end

>>>> >> >

>>>> >> > so that given an object b : buffer, I can call methods

>>>> >> > b#get

>>>> >> > b#Latin1.get

>>>> >> > b#Utf8.get

>>>> >>

>>>> >> It's possible to achieve something like this using methods that
>>>> >> return
>>>> >> objects.  If your nested objects don't need to access the
>>>> >> internal
>>>> >> state of the parent then you might write it like this:

>>>> >>

>>>> >>   class buffer =

>>>> >>     let latin1 = object

>>>> >>       method get = ...

>>>> >>    end

>>>> >>    and utf8 = object

>>>> >>       method get = ...

>>>> >>    end in

>>>> >>    object(self)

>>>> >>      ...

>>>> >>      method get = ...

>>>> >>      method latin1 = latin1

>>>> >>      method utf8 = utf8

>>>> >>    end

>>>> >>

>>>> >> With this approach you can write

>>>> >>

>>>> >>    b#get

>>>> >>    b#latin1#get

>>>> >>    b#utf8#get

>>>> >>

>>>> >> which, apart from some minor orthographic differences, looks
>>>> >> like what
>>>> >> you were aiming for.

>>>> >>

>>>> >> Your intuition that this isn't really idiomatic OCaml is right,
>>>> >> though.  In OCaml, unlike some other languages with classes and
>>>> >> objects, classes are not usually used as namespaces; method
>>>> >> names are
>>>> >> globally (or, rather, "ambiently") scoped, and there's no real
>>>> >> support
>>>> >> for the kind of nesting that you're interested in.  Instead,
>>>> >> people
>>>> >> typically build nested namespaces using modules:

>>>> >>

>>>> >>   module Buffer =

>>>> >>   struct

>>>> >>      let get = ...

>>>> >>

>>>> >>      module Latin1 = struct

>>>> >>         let get = ...

>>>> >>      end

>>>> >>

>>>> >>      module Utf8 = struct

>>>> >>         let get = ...

>>>> >>      end

>>>> >>   end

>>>> >>

>>>> >> With the module approach you write the 'receiver' after the
>>>> >> 'method'
>>>> >> rather than before, but that doesn't seem like a huge hardship.
>>>> >> (10%
>>>> >> of the world manages to get by with VSO languages.)

>>>> >>

>>>> >>   Buffer.get b ...

>>>> >>   Buffer.Latin1.get b ...

>>>> >>   Buffer.Utf8.get b ...

>>>> >>

>>>> >> If you're keen to stick with objects there are slightly more
>>>> >> idiomatic
>>>> >> ways to make it work.  You could, of course, replace the '.'
>>>> >> with a
>>>> >> '_' and define methods 'latin1_get', 'utf8_get' in place of

>>>> >> 'Latin1.get', 'Utf8.get'.  Or you could select the encoding
>>>> >> using a
>>>> >> variant type:

>>>> >>

>>>> >>   type enc = Latin1 | Utf8

>>>> >>

>>>> >>   class buffer =

>>>> >>   object (self)

>>>> >>      method get = function

>>>> >>          | Latin1 -> ...

>>>> >>          | Utf8 -> ...

>>>> >>   end

>>>> >>

>>>> >> Of course, the order of the words in an invocation changes
>>>> >> again, but
>>>> >> there's no real increase in complexity for the caller:

>>>> >>

>>>> >>   b#get Latin1

>>>> >>   b#get Utf8

>>>> >>

>>>> >> This last approach can be taken quite far -- for example, you
>>>> >> could
>>>> >> enrich the type 'enc' so that the return type of 'get' varies

>>>> >> according to the encoding.

>>>> >>

>>>> >> Kind regards,

>>>> >>

>>>> >> Jeremy

>>>> >>

>>>> >>

>>>> >> --

>>>> >> ------------------------------------------------------------

>>>> >> Gerd Stolpmann, Darmstadt, Germany    gerd@gerd-stolpmann.de

>>>> >> My OCaml site:          http://www.camlcity.org

>>>> >> Contact details:        http://www.camlcity.org/contact.html

>>>> >> Company homepage:       http://www.gerd-stolpmann.de

>>>> >> ------------------------------------------------------------

>>>> >>

>>>> >

>> 



[-- Attachment #2: Type: text/html, Size: 17134 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2017-02-10 15:49 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-09 20:36 [Caml-list] namespace inside object? Steffen Smolka
2017-02-09 22:55 ` Jeremy Yallop
2017-02-09 23:19   ` Steffen Smolka
2017-02-09 23:37     ` Gerd Stolpmann
2017-02-09 23:54       ` Steffen Smolka
2017-02-10  2:01         ` Yaron Minsky
2017-02-10  3:16           ` Steffen Smolka
2017-02-10  3:32             ` Yaron Minsky
2017-02-10  9:38             ` Leo White
2017-02-10 14:40               ` Evgeny Roubinchtein
2017-02-10 15:16                 ` Markus Mottl
2017-02-10 15:49                 ` Leo White

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).