From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by sympa.inria.fr (Postfix) with ESMTPS id 171C67EEBF for ; Wed, 19 Aug 2015 00:26:02 +0200 (CEST) Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of anthony.tavener@gmail.com) identity=pra; client-ip=209.85.212.180; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="anthony.tavener@gmail.com"; x-sender="anthony.tavener@gmail.com"; x-conformance=sidf_compatible Received-SPF: Pass (mail2-smtp-roc.national.inria.fr: domain of anthony.tavener@gmail.com designates 209.85.212.180 as permitted sender) identity=mailfrom; client-ip=209.85.212.180; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="anthony.tavener@gmail.com"; x-sender="anthony.tavener@gmail.com"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of postmaster@mail-wi0-f180.google.com) identity=helo; client-ip=209.85.212.180; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="anthony.tavener@gmail.com"; x-sender="postmaster@mail-wi0-f180.google.com"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A0CJAgBWsNNVlLTUVdFdg29aDwaDH6oqkAuCK4V7AoExB0wBAQEBAQESAQEBAQcLCwkfMIQjAQEBAwESER0BGxACCAMBAwELBgULDQ0dAgIhAQERAQUBChIGEwgKCAEHh3YBAwoIDa4RgS8+MYtAgWyCeYsDChknAwpXhQABAQEBAQUBAQEBAQEBFQEFDotFgk+CNwQHgmmBQwWFbAyHXIRAgw6FBIV7gW2CEJBphWoSI4EXEQaCHRyBch8zgkwBAQE X-IPAS-Result: A0CJAgBWsNNVlLTUVdFdg29aDwaDH6oqkAuCK4V7AoExB0wBAQEBAQESAQEBAQcLCwkfMIQjAQEBAwESER0BGxACCAMBAwELBgULDQ0dAgIhAQERAQUBChIGEwgKCAEHh3YBAwoIDa4RgS8+MYtAgWyCeYsDChknAwpXhQABAQEBAQUBAQEBAQEBFQEFDotFgk+CNwQHgmmBQwWFbAyHXIRAgw6FBIV7gW2CEJBphWoSI4EXEQaCHRyBch8zgkwBAQE X-IronPort-AV: E=Sophos;i="5.15,705,1432591200"; d="scan'208";a="174009066" Received: from mail-wi0-f180.google.com ([209.85.212.180]) by mail2-smtp-roc.national.inria.fr with ESMTP/TLS/RC4-SHA; 19 Aug 2015 00:26:01 +0200 Received: by wicja10 with SMTP id ja10so105721540wic.1 for ; Tue, 18 Aug 2015 15:26:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=BqSN2k7uGqbtTcssWChvreR0EpMM40+kPi8u+koUUiQ=; b=ay9bGSmgp2yCHCZOFt7nKho+jb5IH+OyDCP0W3/kvWzO04gDwLrkhe+xed2SQnqDP6 UQTanPWm16GGGIKyVuh9VEhd8ewiEoG7EIalZ4/lRna3LUioxd77VEXpPHh8mchemPcf qlXeVx1uQy7N4kMHO1gj3Ap5xiGuZSIxDREp1P7VRARP9zoYS+qgapb368rohF1mkP6I 7SI1SrTLsgQTfR02j9DmmBEumU/c4UOWMlKJGdHa4IWe0V0A8bwONlgOQ6qE5L07EFhx TqD5Fn/kXuk7GJAzgibQAtrAVVBM4VXXnrYHbqzEd686aRKuoir5XZbbD3W59iBsvXjj zWMQ== MIME-Version: 1.0 X-Received: by 10.180.39.201 with SMTP id r9mr3503435wik.92.1439936760682; Tue, 18 Aug 2015 15:26:00 -0700 (PDT) Received: by 10.28.93.4 with HTTP; Tue, 18 Aug 2015 15:26:00 -0700 (PDT) In-Reply-To: References: <55BF75F6.1040006@bioquant.uni-heidelberg.de> <8E1A640CE3374EB492981ADB0A2DA5C6@erratique.ch> <20150804092633.GC5689@frosties> <5C2023F4AF0549F58F3E4C9A6F8ABE84@erratique.ch> <20150814105551.GD31364@frosties> <55CDD0F2.1090200@zoho.com> <20150818111134.GA11154@frosties> Date: Tue, 18 Aug 2015 16:26:00 -0600 Message-ID: From: Anthony Tavener To: Gabriel Scherer Cc: "caml-list@inria.fr" Content-Type: multipart/alternative; boundary=001a11c24eb41e9f4d051d9d673f Subject: Re: [Caml-list] destructive local opens --001a11c24eb41e9f4d051d9d673f Content-Type: text/plain; charset=UTF-8 (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 >> > > --001a11c24eb41e9f4d051d9d673f Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
(TL;DR: I commonly want to specify paths -uniquely- f= or identifiers in local
scopes (function, module) which have no m= eans to do this.)

As I run into this yet again, mo= ments ago...

I do often want the ability to be cle= ar that something is not to be shadowed
by the opened scope... to= specify it's from the local (usually function) scope.
Part o= f the reason is for code clarity, but also to safeguard against possible
later changes in the *opened* module (introducing the same identifi= er).

=C2=A0 let init flags =3D
=C2=A0 = =C2=A0 M.(init (flag1 + flag2 + flags)) (* flags is intended to be 'loc= al', but it could be shadowed by a value in M *)

Where M provides 'init', 'flag1', 'flag2', and &= #39;+', but 'flags' is in the
local (function) contex= t. 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
<= div>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...

=C2=A0 l= et init flags =3D
=C2=A0 =C2=A0 M.(init (flag1 + flag2 + l:flags)= ) (* illustrative -- not a proposal! *)

I sometime= s consider using naming conventions, but I don't want to explicitly
make function arguments something like l_flags, l_point, etc. That w= ould 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, w= hich 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 o= f recursive unopen came up...

In response, Gabriel= wisely remarked:

=C2=A0"It is remarkable tha= t programming languages have avoided introducing
=C2=A0 explicit = weakening (the popping of a symbol out of scope) for now, and
=C2= =A0 I think it is a property that should be preserved. We're not yet re= ady
=C2=A0 to go there."

Good advic= e when the thread was spinning out of control and probably not going
<= div>to settle on anything realistic or favorable. Even though there might b= e merit
in pursuing fine-grained scope-popping as its own topic.<= /div>

I think there is a simpler gain to be had from the= idea of being able to specify
the path of the current context. &= quot;Current context" would need to be
something sensible, a= nd 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 uni= quely specify the path to what
*will become* A.identifier? As the= bare "identifier" can be shadowed by any
modules opene= d 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 a= m using an
"identifier" which could reasonably be expec= ted to exist now or later in the
other modules being used. I do k= eep opens to a minimum, but often an entire
expression will be in= a local open (to bring in operators), and there,
again... I woul= d like that clarity, and safeguard against changes which might
ha= ppen 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 solution= s.
But if there are ideas, maybe the same thing or something simi= lar can also
apply to this problem of "escaping" a loca= l open? They are very similar, but
one is module-scope, while I t= hink 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 mi= ght have
different use-cases.


On Tue, Aug 18, 2015 at 7:= 00 AM, Gabriel Scherer <gabriel.scherer@gmail.com> w= rote:
Note that the dual= feature does not exist for variant constructors, because it is easy to def= ine only on the constructor at the toplevel of the pattern, and nested patt= erns get us in muddy waters.

On Tue, Aug 18= , 2015 at 2:52 PM, David Allsopp <dra-news@metastack.com> wrote:
Goswin von Brederlow wrot= e:
> On Fri, Aug 14, 2015 at 01:28:50PM +0200, Drup wrote:
> >
> > >You can't qualifylocal values or values of the surroundin= g module so
> > >that is a no go.
> > >
> > >I also often use local open to access records, as in:
> > >
> > >let r =3D M.({ x =3D 1; y; z =3D depth; }) in
> >
> > You can avoid the local open altogether and write it like that: > >
> >=C2=A0 =C2=A0 =C2=A0let r =3D {M. x =3D 1; y; z =3D depth } in
> >
> > It's even shorter.
>
> That only works because newer ocaml disambiguises (is that a word?) re= cord
> So it's implicitly using M.y =3D y and M.z =3D 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 b= y Americans!

But this isn't related to the disambiguation features of OCaml 4.01+. T= hose allow you to write things like:

type t =3D {x : int}
type u =3D {x : int; y : string}

let foo =3D {x =3D 1}
let bar =3D {x =3D 42; y =3D ""}

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 =3D 1; M.y =3D y; M.z =3D depth}

but this was "silly", since it's not possible to use non-equi= valent module paths for labels, so OCaml 3.08 changed it so that you only n= eeded to put the module path on one label (and it doesn't have to be th= e 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} t= o mean {y =3D y}. So while you can use local open as you're using it, y= ou've been able to do it as a totally unambiguous language feature for = quite some time.


David


--
Caml-list mailing list.=C2=A0 Subscription management and archives:
https://sympa.inria.fr/sympa/arc/caml-list
Beginner's list: http://groups.yahoo.com/group/ocam= l_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


--001a11c24eb41e9f4d051d9d673f--