From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@sympa.inria.fr Delivered-To: caml-list@sympa.inria.fr Received: from mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by sympa.inria.fr (Postfix) with ESMTPS id 4C38A800BE for ; Fri, 10 Feb 2017 00:54:36 +0100 (CET) Authentication-Results: mail3-smtp-sop.national.inria.fr; spf=None smtp.pra=sjs429@cornell.edu; spf=Pass smtp.mailfrom=sjs429@cornell.edu; spf=Pass smtp.helo=postmaster@limerock03.mail.cornell.edu Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of sjs429@cornell.edu) identity=pra; client-ip=128.84.13.243; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="sjs429@cornell.edu"; x-sender="sjs429@cornell.edu"; x-conformance=sidf_compatible Received-SPF: Pass (mail3-smtp-sop.national.inria.fr: domain of sjs429@cornell.edu designates 128.84.13.243 as permitted sender) identity=mailfrom; client-ip=128.84.13.243; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="sjs429@cornell.edu"; x-sender="sjs429@cornell.edu"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: Pass (mail3-smtp-sop.national.inria.fr: domain of postmaster@limerock03.mail.cornell.edu designates 128.84.13.243 as permitted sender) identity=helo; client-ip=128.84.13.243; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="sjs429@cornell.edu"; x-sender="postmaster@limerock03.mail.cornell.edu"; x-conformance=sidf_compatible; x-record-type="v=spf1" IronPort-PHdr: =?us-ascii?q?9a23=3AQsSLQBavgKi2Yg5nxm+RM3f/LSx+4OfEezUN459i?= =?us-ascii?q?sYplN5qZr8S8bnLW6fgltlLVR4KTs6sC0LuK9fC+EjVZqb+681k6OKRWUBEEjc?= =?us-ascii?q?hE1ycBO+WiTXPBEfjxciYhF95DXlI2t1uyMExSBdqsLwaK+i764jEdAAjwOhRo?= =?us-ascii?q?LerpBIHSk9631+ev8JHPfglEnjSwbLd9IRmsrgjct8YajZZ/Jq0s1hbHv3xEdv?= =?us-ascii?q?hMy2h1P1yThRH85smx/J5n7Stdvu8q+tBDX6vnYak2VKRUAzs6PW874s3rrgTD?= =?us-ascii?q?QhCU5nQASGUWkwFHDBbD4RrnQ5r+qCr6tu562CmHIc37SK0/VDq+46t3ThLjlT?= =?us-ascii?q?wKPCAl/m7JlsNwjbpboBO/qBx5347Ue5yeOP5ncq/AYd8WWW9NU8BMXCJDH4y8?= =?us-ascii?q?dZMCAOgPPehYoYfzpEYAowWiCgS3Huzj1iVFi2Xq0aEm0eksFxzN0gw6H9IJtX?= =?us-ascii?q?TZtMj7NLsMXuC7wqnH0zPDZO5L1zf474jIdhMhruuRVr93asrRzE4vFwfGjlqK?= =?us-ascii?q?soHqIyiV2v4RvGic9epgU/ygi2ojqw1rvDeg29osh5DPi4kIxF7E8iB5z5w0Jd?= =?us-ascii?q?2+UEN7bsCrEIFNuC2DLIt2XsQiQ2VwuCY/0LIGv5i7cDIXx5s53xLQd+aIc42M?= =?us-ascii?q?4h3/VeaRPTd5iGhieLKliBa/91WrxO7kVsSszVpGsClInsPPu30CzRDf98aKRu?= =?us-ascii?q?Fj8kqu1zuDzx7f5v1ALEwulqfWK4QtzqAtmpYPq0jPAyv7lUHwgaSLbEsr4PKo?= =?us-ascii?q?5P7iYrj+pp+TKYt0igbmP6Qqm8y/BPo3MhIJX2eH+uSwyLPu8Vf8QLpQj/02lr?= =?us-ascii?q?PVv4zdJcQBoK62HQtV0oI55xmhEjimzcwUnXgBLF1bZBKKl5XlN0/NLfziDvqy?= =?us-ascii?q?jE6gnCplyvzcILHsDZvAImDGkLj7fLZ970BcyBA0zdBa/59UEbMBIOn8V0PvsN?= =?us-ascii?q?HVFQM2Mwuuw+bhFtp90oceVXiRDaCELaPeqUWI6f43I+mQeI8Vvy7wJOQ/6P7r?= =?us-ascii?q?iX81gFsdfaiy3ZsLc324BfRnI0CBYXX2mNsBEGEKvhA/TOPwklGCXyRTND6OWP?= =?us-ascii?q?cT6ys3QLm6CoPbQ4mrhvTV3SG1GbVZa3pKT0uQFnPwcoyCXbEAZXTBDNVml2k/?= =?us-ascii?q?SbWvRYInnSqrswv5wvIzNe/T/i4RnZn4ktNy/evekRV0+DBpWZfOm1qRRn15yz?= =?us-ascii?q?tbDwQ927py9Akkkg+O?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0B4AQD0AJ1Yh/MNVIBdGwEBAQMBAQEJA?= =?us-ascii?q?QEBFwEBBAEBCgEBgkSBQ1UDMQeDUoE2iUSRGYgMh3mHPyWFfIJnB0MUAQEBAQE?= =?us-ascii?q?BAQEBAQESAQEBCgsJCh0vgjMbAYIaAQEEASMELiQFCwEIAgsDCioCAiEBEgEFA?= =?us-ascii?q?RwGDgUJiVMDDQgFCZI8kQ0/jAKBazqHOw1FB4NCCwEBAQEBIhKLKYJRgkGCSIJ?= =?us-ascii?q?fBYkMhzWKdzqIMYFeg2wDhBaRBYo1hxkUHoEVNoEfHxMIFxM8FwWDb4JVVwGJe?= =?us-ascii?q?gEBAQ?= X-IPAS-Result: =?us-ascii?q?A0B4AQD0AJ1Yh/MNVIBdGwEBAQMBAQEJAQEBFwEBBAEBCgE?= =?us-ascii?q?BgkSBQ1UDMQeDUoE2iUSRGYgMh3mHPyWFfIJnB0MUAQEBAQEBAQEBAQESAQEBC?= =?us-ascii?q?gsJCh0vgjMbAYIaAQEEASMELiQFCwEIAgsDCioCAiEBEgEFARwGDgUJiVMDDQg?= =?us-ascii?q?FCZI8kQ0/jAKBazqHOw1FB4NCCwEBAQEBIhKLKYJRgkGCSIJfBYkMhzWKdzqIM?= =?us-ascii?q?YFeg2wDhBaRBYo1hxkUHoEVNoEfHxMIFxM8FwWDb4JVVwGJegEBAQ?= X-IronPort-AV: E=Sophos;i="5.35,138,1484002800"; d="scan'208,217";a="212706954" Received: from limerock03.mail.cornell.edu ([128.84.13.243]) by mail3-smtp-sop.national.inria.fr with ESMTP; 10 Feb 2017 00:54:23 +0100 X-CornellRouted: This message has been Routed already. Received: from exchange.cornell.edu (sf-e2013-02.exchange.cornell.edu [10.22.40.49]) by limerock03.mail.cornell.edu (8.14.4/8.14.4_cu) with ESMTP id v19NsMRK029832 for ; Thu, 9 Feb 2017 18:54:22 -0500 Received: from sf-e2013-10.exchange.cornell.edu (10.22.40.57) by sf-e2013-02.exchange.cornell.edu (10.22.40.49) with Microsoft SMTP Server (TLS) id 15.0.1210.3; Thu, 9 Feb 2017 18:54:11 -0500 Received: from mail-wj0-f199.google.com (209.85.210.199) by exchange.cornell.edu (10.22.40.57) with Microsoft SMTP Server (TLS) id 15.0.1210.3 via Frontend Transport; Thu, 9 Feb 2017 18:54:11 -0500 Received: by mail-wj0-f199.google.com with SMTP id yr2so4176309wjc.4 for ; Thu, 09 Feb 2017 15:54:22 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:sender:in-reply-to:references:from :date:message-id:subject:to:cc; bh=/pZuZ2X6Gh7C/6HZ9DoljYPuKubjjZuD5Yytra82YdU=; b=ce9mFYnxoa8z+rHA2n+iTQcBaFicWiDI5wJRfp/e/hOUzI32fdQ6V3bOA1iOzg/UGC 4nCqb9zLjXATeYNW/2PAGzP6m99ZjkQpkX+4a9rcYmD+raEfuIz5JCeDLV8d0mEBipxQ 3LRnCybOrutuCzv+X2hb0EmjbVtquottMqMS4j9EgwLIHQNQtMXpYARqZoGmPc/WE7bq racJsjNk160jhzt1GpmTmkCgaXBCZ9wViByLhGJdjWr6MFH4f73QkgXfGDAwln5RVRtK gJqmAPMIbC6fzvpQi9TojJ0jrnzDeb0x1zIRoJ+brirUSq+Xad9elSHRbnWGcdcxLYoI G69g== X-Gm-Message-State: AMke39n58fifh2BJMu0kV+C2XohuwUxm45Kd9q0WFIIinUObFfeJHnb1IVdJOJrOjHfLxwMsonMNFkBO0KQzY8lrGEIoeYW27ECYHSvLb54nYvlTBsNE4jSEaLztanG7oW6/QZEW0OcW4+PYWcP4tf/viA8AK7+5rg== X-Received: by 10.28.227.84 with SMTP id a81mr4994224wmh.121.1486684461045; Thu, 09 Feb 2017 15:54:21 -0800 (PST) X-Received: by 10.28.227.84 with SMTP id a81mr4994212wmh.121.1486684460721; Thu, 09 Feb 2017 15:54:20 -0800 (PST) MIME-Version: 1.0 Sender: Received: by 10.28.87.132 with HTTP; Thu, 9 Feb 2017 15:54:20 -0800 (PST) In-Reply-To: <1486683451.12698.83.camel@gerd-stolpmann.de> References: <1486683451.12698.83.camel@gerd-stolpmann.de> From: Steffen Smolka Date: Thu, 9 Feb 2017 18:54:20 -0500 X-Google-Sender-Auth: wAP_Scz-psL8sP8s4PkE3qxeSVM Message-ID: To: Gerd Stolpmann CC: Jeremy Yallop , Caml List Content-Type: multipart/alternative; boundary="001a114b0c822cc733054821b370" X-ORG-HybridRouting: 8a094d06fef3beb72b2f550dfbe843f7 X-ORG-RouteOnPrem: False X-ORG-MsgSource: cmail X-PMX-CORNELL-AUTH-RESULTS: dkim-out=none; Subject: Re: [Caml-list] namespace inside object? --001a114b0c822cc733054821b370 Content-Type: text/plain; charset="UTF-8" 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 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 wrote: > > Dear Steffen, > > On 9 February 2017 at 20:36, Steffen Smolka 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 > ------------------------------------------------------------ > > > --001a114b0c822cc733054821b370 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Yeah, I have seen that there is support for first class mo= dules, that's pretty cool stuff!
I do need dynamic dispatch, though= .

-- Steffen

On Thu, Feb 9, 2017 at 6:37 PM, Gerd Stolpm= ann <info@gerd-stolpmann.de> wrote:
Am Donnerstag, den 09.02.2017, 1= 8:19 -0500 schrieb Steffen Smolka:
Thanks for the detailed answer, Jeremy!

If you're keen to stick with= objects

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

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

I suppose I could achieve the same by turni= ng 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: =C2=A0Let= 9;s assume both the base module and the modified one can use the same modul= e type:

module T =3D sig ... end

Now, define the base module like

module Ba= se : T =3D
=C2=A0 =C2=A0...
end

then, define the modified one:

module Mod : T = =3D
=C2=A0 =C2=A0include Base
=C2=A0 =C2=A0... now over= ride what you need to change but note that there's no dynamic dispatch = ...
end

Of course, you could also use fu= nctors for making these modules.

Now turn this int= o first-class modules and pass them around:

let ba= se =3D (module Base : T)
let mod =3D (module Mod : T)
<= br>
The syntax for unpacking the module is quite cumbersome:

let module M =3D (val base : T) in
M.functio= n ...

Unfortunately, there's nothing simple li= ke base.function.

Compared with objects you get:

  • You can also put types and (to some degree) modu= les into these "code containers"
  • However, there's no = dynamic dispatch except you arrange explicitly for that, e.g. with referenc= es to functions
  • Generally, a heavier syntax, but it might be ok

Gerd

<= div>

Or you could select= the encoding using a=C2=A0variant = type:

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

-- Steffen
=
=C2=A0

On Thu, Feb 9, 2017 at 5:55 PM, Jeremy Yallop <<= a href=3D"mailto:yallop@gmail.com" target=3D"_blank">yallop@gmail.com&g= t; 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 wo= uld
> like to write
>
> class buffer =3D object(self)
>=C2=A0 =C2=A0...
>=C2=A0 =C2=A0method get =3D ...
>
>=C2=A0 =C2=A0module Latin1 =3D struct
>=C2=A0 =C2=A0 =C2=A0method get =3D ...
>=C2=A0 =C2=A0end
>
>=C2=A0 =C2=A0module Utf8 =3D struct
>=C2=A0 =C2=A0 =C2=A0method get =3D ...
>=C2=A0 =C2=A0end
> 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.=C2=A0 If your nested objects don't need to access the internal=
state of the parent then you might write it like this:

=C2=A0 class buffer =3D
=C2=A0 =C2=A0 let latin1 =3D object
=C2=A0 =C2=A0 =C2=A0 method get =3D ...
=C2=A0 =C2=A0end
=C2=A0 =C2=A0and utf8 =3D object
=C2=A0 =C2=A0 =C2=A0 method get =3D ...
=C2=A0 =C2=A0end in
=C2=A0 =C2=A0object(self)
=C2=A0 =C2=A0 =C2=A0...
=C2=A0 =C2=A0 =C2=A0method get =3D ...
=C2=A0 =C2=A0 =C2=A0method latin1 =3D latin1
=C2=A0 =C2=A0 =C2=A0method utf8 =3D utf8
=C2=A0 =C2=A0end

With this approach you can write

=C2=A0 =C2=A0b#get
=C2=A0 =C2=A0b#latin1#get
=C2=A0 =C2=A0b#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.=C2=A0 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 rea= l support
for the kind of nesting that you're interested in.=C2=A0 Instead, peopl= e
typically build nested namespaces using modules:

=C2=A0 module Buffer =3D
=C2=A0 struct
=C2=A0 =C2=A0 =C2=A0let get =3D ...

=C2=A0 =C2=A0 =C2=A0module Latin1 =3D struct
=C2=A0 =C2=A0 =C2=A0 =C2=A0 let get =3D ...
=C2=A0 =C2=A0 =C2=A0end

=C2=A0 =C2=A0 =C2=A0module Utf8 =3D struct
=C2=A0 =C2=A0 =C2=A0 =C2=A0 let get =3D ...
=C2=A0 =C2=A0 =C2=A0end
=C2=A0 end

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

=C2=A0 Buffer.get b ...
=C2=A0 Buffer.Latin1.get b ...
=C2=A0 Buffer.Utf8.get b ...

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

=C2=A0 type enc =3D Latin1 | Utf8

=C2=A0 class buffer =3D
=C2=A0 object (self)
=C2=A0 =C2=A0 =C2=A0method get =3D function
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0| Latin1 -> ...
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0| Utf8 -> ...
=C2=A0 end

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

=C2=A0 b#get Latin1
=C2=A0 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' vari= es
according to the encoding.

Kind regards,

Jeremy


--=20
------------------------------------------------------------
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
------------------------------------------------------------


--001a114b0c822cc733054821b370--