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