Module Base.With_return
with_return f
allows for something like the return statement in C within f
.
There are three ways f
can terminate:
- If
f
callsr.return x
, thenx
is returned bywith_return
. - If
f
evaluates to a valuex
, thenx
is returned bywith_return
. - If
f
raises an exception, it escapeswith_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 the equivalentwith_return
call.
val prepend : 'a return -> f:('b -> 'a) -> 'b return
prepend a ~f
returns a valuex
such that each call tox.return
first appliesf
before applyinga.return
. The call tof
is "prepended" to the call to the originala.return
. A possible use case is to handx
over to another function which returns'b
, a subtype of'a
, or to capture a common transformationf
applied to returned values at several call sites.