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 03133800BE for ; Fri, 10 Feb 2017 04:16:55 +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@limerock01.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.241; 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.241 as permitted sender) identity=mailfrom; client-ip=128.84.13.241; 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@limerock01.mail.cornell.edu designates 128.84.13.241 as permitted sender) identity=helo; client-ip=128.84.13.241; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="sjs429@cornell.edu"; x-sender="postmaster@limerock01.mail.cornell.edu"; x-conformance=sidf_compatible; x-record-type="v=spf1" IronPort-PHdr: =?us-ascii?q?9a23=3A2KQ0phIZXvzAtwsHntmcpTZWNBhigK39O0sv0rFi?= =?us-ascii?q?tYgeIvzxwZ3uMQTl6Ol3ixeRBMOAuq4C27Sd7vyocFdDyK7JiGoFfp1IWk1Nou?= =?us-ascii?q?QttCtkPvS4D1bmJuXhdS0wEZcKflZk+3amLRodQ56mNBXdrXKo8DEdBAj0OxZr?= =?us-ascii?q?KeTpAI7SiNm82/yv95HJbQhFgDWwbalxIRi3ognctsYbipZ+J6gszRfEvmFGcP?= =?us-ascii?q?lMy2NyIlKTkRf85sOu85Nm7i9dpfEv+dNeXKvjZ6g3QqBWAzogM2Au+c3krgLD?= =?us-ascii?q?QheV5nsdSWoZjBxFCBXY4R7gX5fxtiz6tvdh2CSfIMb7Q6w4VSik4qx2UxLjlj?= =?us-ascii?q?sJOCAl/2HWksxwjbxUoBS9pxxk3oXYZJiZOOdicq/BeN8XQ3dKUMRMWCxbGo6z?= =?us-ascii?q?bYUPAeoPM+hbsofzuUcBoACkCgWwHu7i0CNEimP00KA8zu8vERvG3AslH98WrX?= =?us-ascii?q?rUsMv6NKkcUe+ryqnD0CjNb/ZR2Tf564jHaA0qrPaXXbJ1dsrRzUovGBneg1qM?= =?us-ascii?q?sozpJS+a1uMXs2id8eVgUeavh3Q5pA5svzii38EhgZTHiIISz1DL7yR5wIAtKN?= =?us-ascii?q?23VkF7e8OrHIJLtyGGMIt2RtsiQ2RytyY8zL0Ko4O0czYSxJs73RHfbviHfJSJ?= =?us-ascii?q?4hL/VOedOzB4hGhqeL+5mh288lCgx/XhWsWq01tGtClIn9bWunwQ2RHf8NaLR/?= =?us-ascii?q?Rg8ku52zuC2Brf5vxaLU00j6bWKIAtzqQym5YNt0nIAzX4l1/sjKCMc0Up4uio?= =?us-ascii?q?5PrjYrXhvpKcM450igTgPaQ0ncywHec4PhQTU2SB/OSzzrzj/UnjTLpWif02iK?= =?us-ascii?q?/Zv47eJcQfvKK2HRJa0ps75xa+CTepzsgYkGEaIF5bex+LlYvkNl7ULPzlA/qz?= =?us-ascii?q?mUqgnTh2y/zeO73uGJTNLnzNkLf7erZ97lZRyBExzdBE6J9YFLUMLenvVU/2rt?= =?us-ascii?q?zYCAE2Mwiww+r9Ftpyy54eVXqVAqCFKKPSrUOI5uU3LuaQfoAVvTL9J+Eh5/7v?= =?us-ascii?q?ln85hUQQfbKp3JsScHC3BO5qI0SfYXr2g9cOC30GvgQkTL+itFrXYDdJYHD6eq?= =?us-ascii?q?M6/TIqQNa3CIbFXYO8qL6I2iqgAodba3wAAVeJRyTGbYKBDswQZSycL8kpqTkD?= =?us-ascii?q?UbuoA9s60BaqtwbSwKEhJe3O/CAcsdTu2MUjtL6brg076TEhV5fV6GqKVWwh2z?= =?us-ascii?q?pQHzI=3D?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0CJAQDjL51YhvENVIBeGwEBAQMBAQEJA?= =?us-ascii?q?QEBFgEBAQMBAQEJAQEBhAcxJAMxB4NSgTaJRJEZiAyHeQWHOiWFfIJnB0MUAQE?= =?us-ascii?q?BAQEBAQEBAQESAQEBCgkLCh0vgjMbAYIaAQEEASMELiQFCwEIAgsDChUVAgIhA?= =?us-ascii?q?RIBBQEcBg4FCYlTAw0IBQmSOpENP4wCgWs6hzwNRQeDQgsBAQEBASISiymCUYJ?= =?us-ascii?q?BAYJHgl8BBIkMhzWKdzqIMYFeg2wDhBaRBYo1hxkUHoEVNoEfHxMIFxM8FwWDb?= =?us-ascii?q?zkdgX9XAYl6AQEB?= X-IPAS-Result: =?us-ascii?q?A0CJAQDjL51YhvENVIBeGwEBAQMBAQEJAQEBFgEBAQMBAQE?= =?us-ascii?q?JAQEBhAcxJAMxB4NSgTaJRJEZiAyHeQWHOiWFfIJnB0MUAQEBAQEBAQEBAQESA?= =?us-ascii?q?QEBCgkLCh0vgjMbAYIaAQEEASMELiQFCwEIAgsDChUVAgIhARIBBQEcBg4FCYl?= =?us-ascii?q?TAw0IBQmSOpENP4wCgWs6hzwNRQeDQgsBAQEBASISiymCUYJBAYJHgl8BBIkMh?= =?us-ascii?q?zWKdzqIMYFeg2wDhBaRBYo1hxkUHoEVNoEfHxMIFxM8FwWDbzkdgX9XAYl6AQE?= =?us-ascii?q?B?= X-IronPort-AV: E=Sophos;i="5.35,138,1484002800"; d="scan'208,217";a="212714149" Received: from limerock01.mail.cornell.edu ([128.84.13.241]) by mail3-smtp-sop.national.inria.fr with ESMTP; 10 Feb 2017 04:16:53 +0100 X-CornellRouted: This message has been Routed already. Received: from exchange.cornell.edu (sf-e2013-04.exchange.cornell.edu [10.22.40.51]) by limerock01.mail.cornell.edu (8.14.4/8.14.4_cu) with ESMTP id v1A3Gqx7011135 for ; Thu, 9 Feb 2017 22:16:52 -0500 Received: from sf-e2013-10.exchange.cornell.edu (10.22.40.57) by sf-e2013-04.exchange.cornell.edu (10.22.40.51) with Microsoft SMTP Server (TLS) id 15.0.1210.3; Thu, 9 Feb 2017 22:16:40 -0500 Received: from mail-wm0-f72.google.com (74.125.82.72) 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 22:16:41 -0500 Received: by mail-wm0-f72.google.com with SMTP id c85so7430378wmi.6 for ; Thu, 09 Feb 2017 19:16:51 -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=bZyCsG8o40wxrA2AX0szK5xECSR918myvrZ3rX9zzMY=; b=fAAGkoelualVILfB+xOXBBJG40PVcnVOWhMe64hla8KiHp3GTbal2ob/dDPzZt26oT VIRqm726/aevszvRohNWoy4s61gLCH2EMdR4M0hvaRwwWOaw26U6i+lg27f1U8JmY9Dx oWQrWhW0YpaNdZCMxnFl5ka4+7GyKo+vdLsQAW6Q6m8yQqoY0P3yIizbYvoQ9kesotik WDm0OOip3uC7/2dwNN1SQfLnjF9rRUu2qJXhUwJnSf1wqAvjuJo3B3ilClHrgMKK21OK 2USB5NMIqlzqREMmFBl3pYtPl1gCHvhqP+TvQIkDEpfkCTgR01Nk4Pm6Y7PF7PkE+VNK wchw== X-Gm-Message-State: AMke39nI2amNKFjZKE9fb+yMXZCvzku5zQwIXjqxqjMdPpiIkvatK+YbR3yfXCz5cD7rknX4888d+6imm1dai+ncirqiDHHkDSSIvUvjuyiSicJ9eXUpkK1vTaeZBAkz9tW+vDhHtkF6HD9l+ww9eTvIC5cyjVzlJA== X-Received: by 10.28.206.136 with SMTP id e130mr24540372wmg.121.1486696610768; Thu, 09 Feb 2017 19:16:50 -0800 (PST) X-Received: by 10.28.206.136 with SMTP id e130mr24540353wmg.121.1486696610230; Thu, 09 Feb 2017 19:16:50 -0800 (PST) MIME-Version: 1.0 Sender: Received: by 10.28.87.132 with HTTP; Thu, 9 Feb 2017 19:16:49 -0800 (PST) In-Reply-To: References: <1486683451.12698.83.camel@gerd-stolpmann.de> From: Steffen Smolka Date: Thu, 9 Feb 2017 22:16:49 -0500 X-Google-Sender-Auth: EHyE9v0ANXGR74KUogsQirMbEA0 Message-ID: To: Yaron Minsky CC: Gerd Stolpmann , Jeremy Yallop , Caml List Content-Type: multipart/alternative; boundary="94eb2c1941145785ec0548248715" X-ORG-HybridRouting: bf420b1027163ea7bdf8e0f3ac625754 X-ORG-RouteOnPrem: False X-ORG-MsgSource: cmail X-PMX-CORNELL-AUTH-RESULTS: dkim-out=none; Subject: Re: [Caml-list] namespace inside object? --94eb2c1941145785ec0548248715 Content-Type: text/plain; charset="UTF-8" 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 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 > 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 > > 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 > >> ------------------------------------------------------------ > >> > > > --94eb2c1941145785ec0548248715 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Right....but you have to explicitly make that choice when = you implement `f`. With objects on the other hand, somebody may write a bas= e implementation c:

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

Later on, somebody else may refine this implementation by overwrit= ing c#bar:

class c2 =3D object(this)
=C2= =A0 inherit c
=C2=A0 method bar =3D ... (* new definition *)<= /div>
end

Now c2#foo will invoke the new defin= ition 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 in= heritance give you the ability to extend modules in ways that weren't n= ecessarily anticipated by the original author of the module. And yet all th= e 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 be= en a bit confused about what the term "dynamic dispatch"
means, but don't first class modules provide what you want? After all,<= br> when you write:

let f (module M : S) x =3D
=C2=A0 =C2=A0 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&= #39;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 mo= dules
>> and no objects. The reason I want to move to objects is that I wan= t to
>> derive a slightly enhanced module from some base implementation. I= nheritance
>> + dynamic dispatch allow me to do so with very little trouble: I c= an 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 imple= mentation
>> needs to replace. I think it won't be quite as natural, but I&= #39;ll give that a
>> try.
>>
>>
>> First-class modules could also be an option:=C2=A0 Let's assum= e both the base
>> module and the modified one can use the same module type:
>>
>> module T =3D sig ... end
>>
>> Now, define the base module like
>>
>> module Base : T =3D
>>=C2=A0 =C2=A0 ...
>> end
>>
>> then, define the modified one:
>>
>> module Mod : T =3D
>>=C2=A0 =C2=A0 include Base
>>=C2=A0 =C2=A0 ... now override what you need to change but note tha= t 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 =3D (module Base : T)
>> let mod =3D (module Mod : T)
>>
>> The syntax for unpacking the module is quite cumbersome:
>>
>> let module M =3D (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 &qu= ot;code
>> containers"
>> However, there's no dynamic dispatch except you arrange explic= itly 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 La= tin1 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? Concret= ely, I
>> > would
>> > 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 tha= t 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 =C2=A0class buffer =3D
>>=C2=A0 =C2=A0 =C2=A0let latin1 =3D object
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0method get =3D ...
>>=C2=A0 =C2=A0 end
>>=C2=A0 =C2=A0 and utf8 =3D object
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0method get =3D ...
>>=C2=A0 =C2=A0 end in
>>=C2=A0 =C2=A0 object(self)
>>=C2=A0 =C2=A0 =C2=A0 ...
>>=C2=A0 =C2=A0 =C2=A0 method get =3D ...
>>=C2=A0 =C2=A0 =C2=A0 method latin1 =3D latin1
>>=C2=A0 =C2=A0 =C2=A0 method utf8 =3D utf8
>>=C2=A0 =C2=A0 end
>>
>> With this approach you can write
>>
>>=C2=A0 =C2=A0 b#get
>>=C2=A0 =C2=A0 b#latin1#get
>>=C2=A0 =C2=A0 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.=C2=A0 In OCaml, unlike some other languages with classes a= nd
>> 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.=C2=A0 Inste= ad, people
>> typically build nested namespaces using modules:
>>
>>=C2=A0 =C2=A0module Buffer =3D
>>=C2=A0 =C2=A0struct
>>=C2=A0 =C2=A0 =C2=A0 let get =3D ...
>>
>>=C2=A0 =C2=A0 =C2=A0 module Latin1 =3D struct
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0let get =3D ...
>>=C2=A0 =C2=A0 =C2=A0 end
>>
>>=C2=A0 =C2=A0 =C2=A0 module Utf8 =3D struct
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0let get =3D ...
>>=C2=A0 =C2=A0 =C2=A0 end
>>=C2=A0 =C2=A0end
>>
>> With the module approach you write the 'receiver' after th= e 'method'
>> 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 =C2=A0Buffer.get b ...
>>=C2=A0 =C2=A0Buffer.Latin1.get b ...
>>=C2=A0 =C2=A0Buffer.Utf8.get b ...
>>
>> If you're keen to stick with objects there are slightly more i= diomatic
>> ways to make it work.=C2=A0 You could, of course, replace the '= ;.' with a
>> '_' and define methods 'latin1_get', 'utf8_get= ' in place of
>> 'Latin1.get', 'Utf8.get'.=C2=A0 Or you could selec= t the encoding using a
>> variant type:
>>
>>=C2=A0 =C2=A0type enc =3D Latin1 | Utf8
>>
>>=C2=A0 =C2=A0class buffer =3D
>>=C2=A0 =C2=A0object (self)
>>=C2=A0 =C2=A0 =C2=A0 method 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 =C2=A0end
>>
>> 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 =C2=A0b#get Latin1
>>=C2=A0 =C2=A0b#get Utf8
>>
>> This last approach can be taken quite far -- for example, you coul= d
>> enrich the type 'enc' so that the return type of 'get&= #39; varies
>> according to the encoding.
>>
>> Kind regards,
>>
>> Jeremy
>>
>>
>> --
>> ------------------------------------------------------------<= br> >> Gerd Stolpmann, Darmstadt, Germany=C2=A0 =C2=A0 gerd@gerd-stolpmann.de
>> My OCaml site:=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 http://www.camlcity= .org
>> Contact details:=C2=A0 =C2=A0 =C2=A0 =C2=A0 http://www.= camlcity.org/contact.html
>> Company homepage:=C2=A0 =C2=A0 =C2=A0 =C2=A0http://www.gerd-sto= lpmann.de
>> ------------------------------------------------------------<= br> >>
>

--94eb2c1941145785ec0548248715--