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

Request: evaluation order of 'let ... and ...' #7586

Closed
vicuna opened this issue Jul 14, 2017 · 4 comments
Closed

Request: evaluation order of 'let ... and ...' #7586

vicuna opened this issue Jul 14, 2017 · 4 comments

Comments

@vicuna
Copy link

vicuna commented Jul 14, 2017

Original bug ID: 7586
Reporter: @stedolan
Assigned to: @alainfrisch
Status: resolved (set by @alainfrisch on 2017-08-31T14:54:04Z)
Resolution: suspended
Priority: normal
Severity: feature
Category: language features
Monitored by: @gasche @yallop

Bug description

It would be useful if the evaluation order of let p1 = e1 and p2 = e2 in ... were the same as match e1, e2 with p1, p2 -> ....

According to the manual, the evaluation order is currently unspecified, with the only constraint being that e1 is evaluated before p1 and e2 before p2. Concretely, both ocamlc and ocamlopt choose the order e1, p1, e2, p2.

I would like to specify that both e1 and e2 are evaluated (in whatever order) before p1 and p2 are evaluated (in whatever order). This would make let ... and ... consistent with match, where the scrutinee is evaluated before the pattern, choosing for instance the order e1, e2, p1, p2.

This would be particularly useful for multicore, where I envisage having a combinator:

val async : (unit -> 'a) -> 'a Lazy.t

which may begin forcing the supplied computation in a different thread. With the modified semantics for let ... and ..., we could then write:

let lazy x = async f and lazy y = async g in ...

allowing f and g to be evaluated in parallel, rather than forcing f before computation of g begins.

Technically, this change would affect existing programs. However, the difference between the evaluation order is only observable to programs that use side-effecting patterns and rely on the intentionally undocumented evaluation order of let rec.

@vicuna
Copy link
Author

vicuna commented Jul 15, 2017

Comment author: @gasche

At first I wasn't fond of the proposal cause it means that

let p1 = e1 and p2 = e2 in e

cannot be desugared into

let p1 = e1 in
let p2 = e2 in e

(or "let p2 .. let p1 ..")

where scope allows. On the other hand, it does allow desugaring into

let x1 = e1 in
let x2 = e2 in
let p1 = x1 in
let p2 = x2 in e

(or "let x2 .. let x1 ..", or "let p2 .. let p1 ..")

@vicuna
Copy link
Author

vicuna commented Jul 15, 2017

Comment author: @yallop

There's also the following scope-preserving desugaring, similar to the 'match' equivalence mentioned in the description

let p1 = e1 and p2 = e2 in e
~>
let p1, p2 = e1, e2 in e

With the current semantics this is a valid desugaring. With the proposed semantics the desugaring can actually be used as a definition of 'let ... and', since it doesn't introduce any additional constraints on evaluation order.

(Nit: the current implementation has some additional differences in the typing of 'let in', which supports GADT refinement and existentials, and 'let ... and', which doesn't. To really use the desugaring as a definition those would probably need to be addressed.)

@vicuna
Copy link
Author

vicuna commented Jul 17, 2017

Comment author: @alainfrisch

However, the difference between the evaluation order is only observable to programs that use side-effecting patterns and rely on the intentionally undocumented evaluation order of let rec.

The change also affects the case of partial patterns and side-effecting or non-terminating expressions.

It also affects life-time of values (and memory usage) since it forces keeping the values for e1 and e2, while the patterns could only keep sub-values live.

===========

Without the change, users can write:

let lazy x, lazy y = async f, async g in ...

This form makes it explicit that the async calculations start before the results are forced. Is it worth changing the language spec and implementation?

@vicuna
Copy link
Author

vicuna commented Aug 31, 2017

Comment author: @alainfrisch

I don't see a strong case for changing the specification (undefined order) or the current behavior. It is possible to request an explicit evaluation order by binding the tuple (with a let or match...with). At least, nothing prevents from experimenting with the async combinator in the context of the multicore work.

So I'm suspending this request for now. We can always revisit if the need arises later.

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

No branches or pull requests

2 participants