This whole thread makes me wonder whether local opens are worth it. I don't like global open (at all), and shadowing is harmful even in smaller scopes. Local open seems to be used for DSL that have a lot of infix operators (maths, etc.) as demonstrated by the proposal of new warnings and syntax about shadowing of infix operators. If modules have short names (Z, Q from Zarith come to mind, but module-aliasing your favorite monad to "M" would do too), would M.+ be a reasonable infix operator? I would be ready to have slightly more verbose calls to M.>>= if it removes ambiguity and potential shadowing bugs. Of course I don't know if this is compatible with the current syntax. Le 19 août 2015 00:26:00 UTC+02:00, Anthony Tavener a écrit : >(TL;DR: I commonly want to specify paths -uniquely- for identifiers in >local >scopes (function, module) which have no means to do this.) > >As I run into this yet again, moments ago... > >I do often want the ability to be clear that something is not to be >shadowed >by the opened scope... to specify it's from the local (usually >function) >scope. >Part of the reason is for code clarity, but also to safeguard against >possible >later changes in the *opened* module (introducing the same identifier). > > let init flags = > M.(init (flag1 + flag2 + flags)) (* flags is intended to be 'local', >but it could be shadowed by a value in M *) > >Where M provides 'init', 'flag1', 'flag2', and '+', but 'flags' is in >the >local (function) context. When I do this I try to think of a way to >make it >self evident that 'flags' is not from M, but there is no way. Aside >from >bringing it outside the local-open, but then it's more difficult to >build >an expression. > >Vimscript might be one of the worst languages to use as a reference, >but >this >issue does bring to mind the scope prefixes... > > let init flags = >M.(init (flag1 + flag2 + l:flags)) (* illustrative -- not a proposal! >*) > >I sometimes consider using naming conventions, but I don't want to >explicitly >make function arguments something like l_flags, l_point, etc. That >would be >a >horrible widespread style, and doesn't work nicely with named >arguments. >Plus, changing names to do this seems wrong -- it's at the access site >where >you want to disambiguate, which always leads me to think some sigil or >prefix. > >There was an earlier sidetrack which went with ^ as an "unopen" prefix. >At >first, >my interest was piqued. Naturally, the issue of recursive unopen came >up... > >In response, Gabriel wisely remarked: > > "It is remarkable that programming languages have avoided introducing > explicit weakening (the popping of a symbol out of scope) for now, and > I think it is a property that should be preserved. We're not yet ready > to go there." > >Good advice when the thread was spinning out of control and probably >not >going >to settle on anything realistic or favorable. Even though there might >be >merit >in pursuing fine-grained scope-popping as its own topic. > >I think there is a simpler gain to be had from the idea of being able >to >specify >the path of the current context. "Current context" would need to be >something sensible, and I'm not sure yet what would be best, as there >is a >related issue I encounter commonly: > >A way to specify the path of the current module. > >There is no way to do this, right? If I'm in "a.ml", I can't refer to >A.identifier, and there is no other way to uniquely specify the path to >what >*will become* A.identifier? As the bare "identifier" can be shadowed by >any >modules opened afterward. Unlike the general "scope-popping", there is >also >a common language feature like this: self or this. > >I usually want to be explicit with module paths, especially if I am >using an >"identifier" which could reasonably be expected to exist now or later >in the >other modules being used. I do keep opens to a minimum, but often an >entire >expression will be in a local open (to bring in operators), and there, >again... I would like that clarity, and safeguard against changes which >might >happen in the other modules, leading to suprises or need to change >*this* >module for no good reason other than a naming conflict which ideally >can be >prepared against. > >Has there been any discussion about referring to the local module? My >guess >is >that it might be a mild enough problem to not warrant any proposed >solutions. >But if there are ideas, maybe the same thing or something similar can >also >apply to this problem of "escaping" a local open? They are very >similar, but >one is module-scope, while I think the other would be function-scope >(though >module-scope might imply the "right thing" anyway)... I'm not certain, >as >haven't been keeping track of the cases I encounter, and others might >have >different use-cases. > > >On Tue, Aug 18, 2015 at 7:00 AM, Gabriel Scherer > >wrote: > >> Note that the dual feature does not exist for variant constructors, >> because it is easy to define only on the constructor at the toplevel >of the >> pattern, and nested patterns get us in muddy waters. >> >> On Tue, Aug 18, 2015 at 2:52 PM, David Allsopp > >> wrote: >> >>> Goswin von Brederlow wrote: >>> > On Fri, Aug 14, 2015 at 01:28:50PM +0200, Drup wrote: >>> > > >>> > > >You can't qualifylocal values or values of the surrounding >module so >>> > > >that is a no go. >>> > > > >>> > > >I also often use local open to access records, as in: >>> > > > >>> > > >let r = M.({ x = 1; y; z = depth; }) in >>> > > >>> > > You can avoid the local open altogether and write it like that: >>> > > >>> > > let r = {M. x = 1; y; z = depth } in >>> > > >>> > > It's even shorter. >>> > >>> > That only works because newer ocaml disambiguises (is that a >word?) >>> record >>> > So it's implicitly using M.y = y and M.z = depth. >>> > labels when it determines the record type from the first label, >right? >>> >>> Only since you ask: "disambiguates" :o) That said, it's quite common >to >>> see words like "disambiguises" being invented by Americans! >>> >>> But this isn't related to the disambiguation features of OCaml >4.01+. >>> Those allow you to write things like: >>> >>> type t = {x : int} >>> type u = {x : int; y : string} >>> >>> let foo = {x = 1} >>> let bar = {x = 42; y = ""} >>> >>> This is actually a much older notation added in OCaml 3.08. Prior to >>> that, if you hadn't opened a module you had to qualify each label: >>> >>> {M.x = 1; M.y = y; M.z = depth} >>> >>> but this was "silly", since it's not possible to use non-equivalent >>> module paths for labels, so OCaml 3.08 changed it so that you only >needed >>> to put the module path on one label (and it doesn't have to be the >first >>> one, it's just a bit weird to put it in the middle!). >>> >>> OCaml 3.12 added, amongst other record-related goodies, the >shorthand {y} >>> to mean {y = y}. So while you can use local open as you're using it, >you've >>> been able to do it as a totally unambiguous language feature for >quite some >>> time. >>> >>> >>> David >>> >>> >>> -- >>> Caml-list mailing list. Subscription management and archives: >>> https://sympa.inria.fr/sympa/arc/caml-list >>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners >>> Bug reports: http://caml.inria.fr/bin/caml-bugs >>> >> >> > >-- >Caml-list mailing list. Subscription management and archives: >https://sympa.inria.fr/sympa/arc/caml-list >Beginner's list: http://groups.yahoo.com/group/ocaml_beginners >Bug reports: http://caml.inria.fr/bin/caml-bugs -- Simon