caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Jeremy Yallop <yallop@gmail.com>
To: Steffen Smolka <smolka@cs.cornell.edu>
Cc: Caml List <caml-list@inria.fr>
Subject: Re: [Caml-list] namespace inside object?
Date: Thu, 9 Feb 2017 22:55:59 +0000	[thread overview]
Message-ID: <CAAxsn=FzJODdst5Quy2Bu2ZYtpdQ5OW3wvSWeCi2UWr18Gmm7A@mail.gmail.com> (raw)
In-Reply-To: <CAGh2ivAw17fXw_iR4bBPzsK4jXOmrmcYka0HJE77rS+vkcBwVg@mail.gmail.com>

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

  reply	other threads:[~2017-02-09 22:56 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-09 20:36 Steffen Smolka
2017-02-09 22:55 ` Jeremy Yallop [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAAxsn=FzJODdst5Quy2Bu2ZYtpdQ5OW3wvSWeCi2UWr18Gmm7A@mail.gmail.com' \
    --to=yallop@gmail.com \
    --cc=caml-list@inria.fr \
    --cc=smolka@cs.cornell.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).