Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ppx_export mark 2 #1251

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open

ppx_export mark 2 #1251

wants to merge 23 commits into from

Conversation

jaredly
Copy link
Contributor

@jaredly jaredly commented May 10, 2017

taking over from #1206

The purpose of this is to allow you to "export" values from your .re (or .ml) file directly, instead of going through a separate .mli file. I personally think this will be more usable, and in any case it will be more familiar to people coming from javascript.

We first implement it as a ppx, and then we can put some syntactic sugar (like an export keyword) in our reason parser to make it even more ergonomic.

work remaining

  • basic things
  • classes
  • nested modules
  • recursive modules
  • good error reporting
  • various cleanups
  • export as & abstract type export

for example, you can do

let[@export] something: int = 5

let[@export] somefun (arg: int): string = "hello"

type[@export abstract] t = int
let[@export: t list] m = [2;3]

(* you can put an aribtrary signature in here too if you want more power*)
let[@export: val mm: int] mm = something

helpful documents for putting this together

@jaredly jaredly mentioned this pull request May 10, 2017
@jaredly jaredly changed the title [WIP] ppx_export mark 2 ppx_export mark 2 May 10, 2017
@cristianoc
Copy link
Contributor

One can export the whole type, or a more abstract version. Is this supported already?
It's not crucial that this is supported in the first iteration, but to know that it's possible to extend it in future.

For example, here I'm just using modules directly for illustration, but imagine there are .re and .rei files, and a user of the .rei:

module M : { type t; let create : int => t; } = { type t = int; let create n => n };

then this shows that the type is hidden:

# M.create 34 == 34;
Error: This expression has type int but an expression was expected of type M.t 

@jaredly
Copy link
Contributor Author

jaredly commented May 10, 2017

exporting a more abstracted version is not yet supported. I could imagine using an attribute w/ an "export type" to do that kind of thing, but yeah I think that should come as a separate diff.
I'm thinking

module%export M = {
   [@export `abstract]
   type t = int;

  [@export () => t]
  let create () => 23
}

or something

@cristianoc
Copy link
Contributor

Specifying an export level sounds like a promising direction.
In general, there can be many possible levels.
Consider for example the concrete type type mylist = list int, then possible exports include

1. list int
2. list t
3. t
4. no export at all

@jordwalke
Copy link
Member

Would it be too hard to add "export as" in this diff? I'd be concerned that people are all too satisfied without the exporting as "abstract" feature because they are't used to having that capability, and then it never gets added - and then using the "exports" feature is inferior to using interface files. I think we should make it every bit just as good out of the gate. I'm finding that developers don't ask for abstract types, but they desperately need them.

@jaredly
Copy link
Contributor Author

jaredly commented May 11, 2017

Good idea

@jaredly
Copy link
Contributor Author

jaredly commented May 12, 2017

hmmm don't merge yet, I have a different idea

@jaredly
Copy link
Contributor Author

jaredly commented May 13, 2017

Ok, "export as" working across the board! You can now do, for example

type[@export abstract] t = int
let[@export: t] myvar = 10

let%export string_implicit = "str"
let%export char_implicit = 'c'
let%export float_implicit = 1.1
let[@export] int_implicit = 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, my version of OCaml doesn't appear to support this syntactic form.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm, might be new in 4.03?

@jordwalke
Copy link
Member

Looks like some failures on 4.02.3 and 4.04. The 4.02.3 failures might be related to the ppx form we just discussed. Maybe you can use the equivalent syntactic form that would work on all versions. I'm not sure about the 4.04 failures though - looks more like slight differences in printing output.

@jordwalke
Copy link
Member

Also, @let-def can you take a look at the changes too?

@jaredly
Copy link
Contributor Author

jaredly commented May 16, 2017

yeah, I'm not quite sure how I ought to fix the "ocaml 4.04 prints this a little differently"

@cullophid
Copy link

could you not just do export let ... that seems simpler, and would also be more familiar to newcommers.

@let-def
Copy link
Contributor

let-def commented Sep 12, 2017

The proposal https://www.cl.cam.ac.uk/~jdy22/papers/extending-ocamls-open.pdf by @objmagic makes it possible to implement this feature with proper support from the compiler.

@let-def
Copy link
Contributor

let-def commented Sep 12, 2017

In particular, it makes it possible to use the compiler infrastructure for finding names that are valid from the outside (e.g. assuming private type t = int -> int and exported let f : t = fun x -> x + 1, the compiler will rewrite the binding from val f : t to val f : int -> int)

@objmagic
Copy link
Contributor

objmagic commented Sep 13, 2017

Thanks @let-def. The actual patch still needs some polish. And assuming if people are in favor of merging this feature into compiler, you probably will see it in >4.06 since I imagine the PR will go through a pretty long debate... ("looks ok to me" from Xavier, seems ok from Alain Frisch, neutral from Jacques and Leo)

That said, if people are in serious need of this ppx_export, continue working on this feature instead of waiting support from OCaml language is a better idea.

@objmagic
Copy link
Contributor

objmagic commented Dec 2, 2017

open extension pull request was just opened at ocaml/ocaml#1506

@jaredly
Copy link
Contributor Author

jaredly commented Dec 5, 2019

That change ended up in 4.08, so as soon as the 4.08 PR gets merged this might be relevant again?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants