Skip to content

Short syntax for overriding local open#218

Closed
Drup wants to merge 3 commits intoocaml:trunkfrom
Drup:local_open_shadow
Closed

Short syntax for overriding local open#218
Drup wants to merge 3 commits intoocaml:trunkfrom
Drup:local_open_shadow

Conversation

@Drup
Copy link
Copy Markdown
Contributor

@Drup Drup commented Jul 23, 2015

This proposal adds the syntax M.!( ... ) which opens a module locally but silent the shadowing warnings. It is similar to both the shortcut local open syntax M.( ... ) and the shadowing local open syntax let open! M in ...

The proposal is motivated by two points:

  • The shadowing warnings do help to catch various bugs.
  • Local open is very useful to implement EDSL-like functionalities, by shadowing existing operators in a limited scope.

Half of this proposal, and in particular the tests, were done by @Octachron, big thanks to him!

@Drup
Copy link
Copy Markdown
Contributor Author

Drup commented Jul 23, 2015

I was not too sure about were to put the Changes entry, so it went into "languages feature".

@gasche
Copy link
Copy Markdown
Member

gasche commented Jul 23, 2015

In the object language we have override that expresses, per-method, the intent for an identifier to "shadow". In the module language we have ! which expresses (in a very coarse-grained way) the intent for a group of identifiers to shadow. Maybe it would make sense to have a [@shadow] annotation at the identifier-intended-for-shadowing declaration site, that would silence warnings on use and thus remove the need for the ugly !?

(! is "ugly" because it is obviously a tool too blunt for its own good. It is heavy-handed because we cannot afford for readability to be more precise at its use site. So maybe the information should be put somewhere else?)

@Octachron
Copy link
Copy Markdown
Member

that would silence warnings on use and thus remove the need for the ugly !

I don't know, I like the current semantic of open + warnings 44 which warns for any shadowed identifiers. Allowing external module to sneak in shadowing identifiers with just open sounds like a potential source of confusion.

! is "ugly" because it is obviously a tool too blunt for its own good.

Maybe the solution is to use the [@shadow] annotation for open! and variants? So open would warn on any shadowed identifiers and open! only on non-expected shadowed identifiers (i.e. those non marked with [@shadow] ). Combined with some sort of [@shadowing_all] annotations on open and module aliases, it seems like it would allow to express natural tiers of agreement between the module identifiers and the module user:

  • open : no agreement, warns on any shadowed identifiers
  • open!: partial agreement: warns on non-expected shadowed identifiers
  • open M [@shadowing_all]: full agreement, never warns on shadowed identifiers

@gasche
Copy link
Copy Markdown
Member

gasche commented Jul 23, 2015

open!!M? This is getting out of hand. (Also your proposal changes the semantics of open! in a way that makes it emit more warnings, this seems bad.)

In any case, I am fine with the M.!( proposal. I find open! rather ugly but there is no reason to be inconsistent in the short-open notation.

@Drup
Copy link
Copy Markdown
Contributor Author

Drup commented Jul 23, 2015

@gasche : In objects, you know in the definition of a class what you are shadowing. Regardless of warning emission or not, this redefinition doesn't leak to the code using the object. For a module, it's the opposite. I don't feel like a declaration-level shadowing annotation make sense, and it would reduce the value of warnings 44/45.

@Drup Drup force-pushed the local_open_shadow branch from 86d6876 to 7a75f76 Compare July 23, 2015 10:42
@lpw25
Copy link
Copy Markdown
Contributor

lpw25 commented Jul 23, 2015

In the object language we have override

I assume you mean method!, val! and inherit!.

@dbuenzli
Copy link
Copy Markdown
Contributor

dbuenzli commented Aug 3, 2015

Local open is very useful to implement EDSL-like functionalities, by shadowing existing operators in a limited scope.

In practice the M.() notation can lead to very nasty bugs and we should not encourage people to override the warning via M.!(). I would really be in favour of not introducing such a notation.

It seems to me that what @gasche proposes on the mailing list, is a much better solution. I.e. split warning 44 in two, one for alphanumerical identifiers, enabled by default, which makes M.() usage much less dangerous w.r.t. to API evolution and one for operators, not enabled by default, which are less likely to cause problems in practice.

This would also lead to a better error user experience when you do things like:

let sub = String.sub s 3 6 in
let s = String.(uppercase @@ trim sub)

@Drup
Copy link
Copy Markdown
Contributor Author

Drup commented Aug 3, 2015

The issue I personally have with your/gache's proposal is that edsl are not only for operators. I do agree with the whole idea, though.

@dbuenzli
Copy link
Copy Markdown
Contributor

dbuenzli commented Aug 3, 2015

The issue I personally have with your/gache's proposal is that edsl are not only for operators.

Sure there may be constants, functions etc. but one can argue in that in this case it would be bad style/misleading from a code reading perspective to use the same identifiers in scope and the proposal prevents that aswell.

@gasche
Copy link
Copy Markdown
Member

gasche commented Aug 3, 2015

Well having several monad modules that export return and bind and shadow each other does not seem bad style -- as long as it is a pattern accepted in the community. There is a difference between "small module with interface set in stone" and "big module that grows each release, but also has a bunch of useful infix operators".

@dbuenzli
Copy link
Copy Markdown
Contributor

dbuenzli commented Aug 3, 2015

Well having several monad modules that export return and bind and shadow each other does not seem bad style --

Usually bind will be an operator as for return I think that people should prefer identifiers that match the specific domain of the monad.

@Drup Drup force-pushed the local_open_shadow branch from 7a75f76 to d215d7a Compare August 4, 2015 13:44
@damiendoligez damiendoligez added this to the 4.04-or-later milestone Jan 22, 2016
@mshinwell mshinwell removed this from the 4.04 milestone Sep 7, 2016
@mshinwell
Copy link
Copy Markdown
Contributor

Would anyone else like to weigh in on this feature?
This has been languishing for more than a year.

I'm biased because I don't like use of local open anyway, but I do wonder if we should just wait for modular implicits, which will presumably help many of these use cases anyway.

@damiendoligez
Copy link
Copy Markdown
Member

This was discussed in the developer meeting two days ago, where nobody was willing to support it, so we decided to close.

stedolan pushed a commit to stedolan/ocaml that referenced this pull request Feb 20, 2020
Use size in words for all minor heap sizes
mshinwell pushed a commit to mshinwell/ocaml that referenced this pull request Jul 21, 2020
mshinwell pushed a commit to mshinwell/ocaml that referenced this pull request Jul 21, 2020
EmileTrotignon pushed a commit to EmileTrotignon/ocaml that referenced this pull request Jan 12, 2024
* add milestones component and history page
EmileTrotignon pushed a commit to EmileTrotignon/ocaml that referenced this pull request Jan 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants