Skip to content

Commit 506e90c

Browse files
committed
common/mlstdutils: Add ‘return’ statement for OCaml.
This adds a ‘return’ statement as found in other programming languages. You can use it like this: with_return (fun {return} -> some code ... ) where ‘some code’ may either return implicitly (as usual), or may call ‘return x’ to immediately return ‘x’. All returned values must have the same type. The OCaml >= 4.04 implementation is by Petter A. Urkedal and octachron. See this thread: https://sympa.inria.fr/sympa/arc/caml-list/2017-11/msg00017.html The version that works for any OCaml is by me. (Note that my version cannot be nested).
1 parent 0eb2323 commit 506e90c

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

common/mlstdutils/std_utils.ml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,22 @@ let protect ~f ~finally =
598598
finally ();
599599
match r with Either ret -> ret | Or exn -> raise exn
600600

601+
type 'a return = { return: 'b. 'a -> 'b } (* OCaml >= 4.03: [@@unboxed] *)
602+
(* This requires features in OCaml >= 4.04:
603+
let with_return (type a) f =
604+
let exception Return of a in
605+
try f {return = fun ret -> raise (Return ret)} with Return ret -> ret
606+
*)
607+
608+
(* This should work for any version of OCaml, but it doesn't work
609+
* properly for nested with_return statements. When we can assume
610+
* OCaml >= 4.04 we should use the above definition instead.
611+
*)
612+
let with_return f =
613+
let ret = ref None in
614+
try f {return = fun r -> ret := Some r; raise Exit}
615+
with Exit -> match !ret with None -> assert false | Some r -> r
616+
601617
let failwithf fs = ksprintf failwith fs
602618

603619
exception Executable_not_found of string (* executable *)

common/mlstdutils/std_utils.mli

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,20 @@ val protect : f:(unit -> 'a) -> finally:(unit -> unit) -> 'a
347347
case, but requires a lot more work by the caller. Perhaps we
348348
will change this in future.) *)
349349

350+
type 'a return = { return: 'b. 'a -> 'b } (* OCaml >= 4.03: [@@unboxed] *)
351+
val with_return : ('a return -> 'a) -> 'a
352+
(** {v
353+
with_return (fun {return} ->
354+
some code ...
355+
)
356+
v}
357+
emulates the [return] statement found in other programming
358+
languages.
359+
360+
The ‘some code’ part may either return implicitly, or may call
361+
[return x] to immediately return the value [x]. All returned
362+
values must have the same type. *)
363+
350364
val failwithf : ('a, unit, string, 'b) format4 -> 'a
351365
(** Like [failwith] but supports printf-like arguments. *)
352366

0 commit comments

Comments
 (0)