with_return f
allows for something like the return statement in C within f
. There
are three ways f
can terminate:
1. If f
calls r.return x
, then x
is returned by with_return
.
2. If f
evaluates to a value x
, then x
is returned by with_return
.
3. If f
raises an exception, it escapes with_return
.
Here is a typical example:
let find l ~f =
with_return (fun r ->
List.iter l ~f:(fun x -> if f x then r.return (Some x));
None
)
It is only because of a deficiency of ML types that with_return
doesn't have type:
val with_return : 'a. (('a -> ('b. 'b)) -> 'a) -> 'a
but we can slightly increase the scope of 'b, without changing the meaning of the type and then we get
type 'a return = { return : 'b . 'a -> 'b }
val with_return : ('a return -> 'a) -> 'a
But the actual reason we chose to use a record type with polymorphic field is that
otherwise we would have to clobber the namespace of functions with return
and that
is undesirable because return
would get hidden as soon as we open any monad. We
considered names different than return
but everything seemed worse than just having
return
as a record field. We are clobbering the namespace of record fields but that
is much more acceptable.
val with_return : ('a return ‑> 'a) ‑> 'a
val with_return_option : ('a return ‑> unit) ‑> 'a option
Note that with_return_option
allocates ~5 words more than equivalent with_return
call
prepend a ~f
returns a value x
such that each call to x.return
first applies f
before applying a.return
. The call to f
is "prepended" to the call to the
original a.return
. A possible use case is to hand x
over to an other function
which returns 'b
a subtype of 'a
, or to capture a common transformation f
applied to returned values at several call sites.