Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[Caml-list] How an exception could be an argument

5 views
Skip to first unread message

Pierre-Alexandre Voye

unread,
Feb 17, 2012, 1:17:33 PM2/17/12
to caml-list
Hello, I'm trying to implement a scala concept "partial application" in
which one can chains pattern matching function. If the first failed, the
second is tried.
It seems it is impossible to give an exception as argument to a function.



exception Nothing;;

let (<|||>) a b = try a
with

| Nothing -> (try b
with

| Nothing -> raise
Nothing);;

val ( <|||> ) : 'a -> 'a -> 'a = <fun>


(raise Nothing) <|||>
"jj";;

Exception: Nothing.


But if I try :
try (raise Nothing)
with

| Nothing -> (try
"jj"with

| Nothing -> raise
Nothing);;

- : string = "jj"

Is there a workaround ?


Regards,
P-A
--
---------------------
https://twitter.com/#!/ontologiae/
http://linuxfr.org/users/montaigne

--
Caml-list mailing list. Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

Tiphaine Turpin

unread,
Feb 17, 2012, 1:32:07 PM2/17/12
to caml...@inria.fr
This behavior is expected given than OCaml is strict, and your operator
<|||> would be an ordinary function (unlike || and &&). You have to use
either functions (or lazy values) instead of expressions, or options
instead of exceptions.

Tiphaine
> https://twitter.com/#!/ontologiae/ <https://twitter.com/#%21/ontologiae/>

Edgar Friendly

unread,
Feb 17, 2012, 1:34:04 PM2/17/12
to Pierre-Alexandre Voye, caml-list
Here is an example of giving an exception as an argument to a function:

let run_or ~cmd ~err = if Sys.command cmd <> 0 then raise err

and an example usage:

let config_fail = Failure ("Could not configure " ^ p.id) in
run_or ~cmd:("sh configure" ^ config_opt) ~err:config_fail;

The problem with your code seems to be that you're passing in a result, so
the exception is being raised outside your try...with block. OCaml's eager
evaluation means that you'll probably have to pass in a function and an
argument (or just a unit function), meaning that your <|||> will be much
uglier:

let (<|||>) (f,x) (g,y) = try f x with Nothing -> g y

((fun () -> raise Nothing), ()) <|||> ((fun str -> str), "ii")

E.

Vincent Aravantinos

unread,
Feb 17, 2012, 1:50:25 PM2/17/12
to caml...@inria.fr
The arguments are evaluated before being passed to the function.
So in your first test, "Nothing" is raised before even entering "<|||>".
In the second case you're circumventing this by copying directly "raise
Nothing" in the body of the function: this copy-pasting is not
equivalent since you now force the evaluation of "raise Nothing" to
happen within the scope of "try".

* The following could be a workaround:

# let (<|||>) (f1,arg1) (f2,arg2) = try f1 arg1 with Nothing -> try f2
arg2 with Nothing -> raise Nothing;;
val ( <|||> ) : ('a -> 'b) * 'a -> ('c -> 'b) * 'c -> 'b = <fun>

# ((fun _ -> raise Nothing),()) <|||> ((fun _ -> "jj"),());;
- : string = "jj"

It looks a bit heavy on this example because we are working with constants.
But generally the constants come from some function application so it
can fit in a not-so-ugly way in real code.

* If you don't care about the infix, the following induces less parentheses:

# let try_or_try f1 arg1 f2 arg2 = try f1 arg1 with Nothing -> try f2
arg2 with Nothing -> raise Nothing;;
val try_or_try : ('a -> 'b) * 'a -> ('c -> 'b) * 'c -> 'b = <fun>

# try_or_try (fun _ -> raise Nothing) () (fun _ -> "jj") ();;
- : string = "jj"

* Note that you can simplify the second try since "try blah with Nothing
-> raise Nothing" is actually equivalent to "blah"

This yields:

# let (<|||>) (f1,arg1) (f2,arg2) = try f1 arg1 with Nothing -> f2 arg2;;
val ( <|||> ) : ('a -> 'b) * 'a -> ('c -> 'b) * 'c -> 'b = <fun>


On 02/17/2012 01:16 PM, Pierre-Alexandre Voye wrote:
> (raise Nothing) <|||> "jj";;
> Exception: Nothing.
>
> But if I try :
> try (raise Nothing) with
> | Nothing -> (try "jj"with
> | Nothing -> raise Nothing);;
> - : string = "jj"

--
Vincent Aravantinos
Postdoctoral Fellow, Concordia University, Hardware Verification Group
http://users.encs.concordia.ca/~vincent
0 new messages