caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] exn vs option
@ 2012-04-04 20:25 Pierre Chopin
  2012-04-04 20:38 ` John Carr
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Pierre Chopin @ 2012-04-04 20:25 UTC (permalink / raw)
  To: caml-list

[-- Attachment #1: Type: text/plain, Size: 1030 bytes --]

Hi,

I benchmarked two programs, in one case the main function throw an
exception that is caught, in the other the function returns an option that
is pattern matched on.

I noticed that, whether the exception is thrown or not, the option version
is always faster.

Is there any case where it makes sense, performance wise, to use exception
instead of 'a option ?

test1.ml
----------------------------------------------------------------------

exception Foo
let f x =
 if x =1 then raise Foo else ()

;;

 for i = 0 to 10_000_000 do
try
    f 1
with Foo -> ()
done
------------------------------------------------------------------------
test2.ml:
------------------------------------------------------------------------
let f x =
    if x=1 then None else Some ()

;;
for i = 0 to 10_000_000 do
    match f 1 with
        None -> ()
    |   Some s -> s
    done
------------------------------------------------------------------------



-- 
Pierre Chopin,
Chief Technology Officer and co-founder
punchup LLC
pierre@punchup.com

[-- Attachment #2: Type: text/html, Size: 1690 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] exn vs option
  2012-04-04 20:25 [Caml-list] exn vs option Pierre Chopin
@ 2012-04-04 20:38 ` John Carr
  2012-04-04 22:10   ` Julien Verlaguet
  2012-04-05  6:45 ` Raphael Proust
  2012-04-05  9:05 ` Goswin von Brederlow
  2 siblings, 1 reply; 12+ messages in thread
From: John Carr @ 2012-04-04 20:38 UTC (permalink / raw)
  To: Pierre Chopin; +Cc: caml-list


When thinking about performance, consider the "try" keyword to take time
to execute.  A try block pushes an exception handler onto a stack and
pops the stack on exit.  The try block may also interfere with tail call
optimizations.

A loop like

  for i = 0 to 10000000 do try ... done

executes "try" 10000001 times and will run much more slowly than

  try for i = 0 to 10000000 do ... done

where "try" only executes once.

I use options where performance matters, in frequently executed code
where the amount of computation is not much more than the overhead of
a try...with.  For example, I have variants of List.assoc that return
options instead of raising exceptions.

Where performance doesn't matter, i.e. the amount of code in the block
is large or the block is rarely executed, I use exceptions or options
based on convenience.

> I benchmarked two programs, in one case the main function throw an exception
> that is caught, in the other the function returns an option that is pattern
> matched on.
> 
> I noticed that, whether the exception is thrown or not, the option version is
> always faster.
> 
> Is there any case where it makes sense, performance wise, to use exception
> instead of 'a option ?

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] exn vs option
  2012-04-04 20:38 ` John Carr
@ 2012-04-04 22:10   ` Julien Verlaguet
  2012-04-05  1:29     ` Francois Berenger
  0 siblings, 1 reply; 12+ messages in thread
From: Julien Verlaguet @ 2012-04-04 22:10 UTC (permalink / raw)
  To: John Carr; +Cc: Pierre Chopin, caml-list

[-- Attachment #1: Type: text/plain, Size: 2309 bytes --]

2 more use cases:

1) When writing a deep recursion
Throwing an exception will directly jump to your "catch" block without
having to unfold every return call site on the stack one by one. Which can
be much faster if the recursion is very "deep".

2) When your exception is exceptional :-)
If Not_found is never caught, then using exceptions is faster than option
because you don't have to allocate to perform the "find" operation (the
difference should be minimal though).
Plus it makes your code more readable, you don't have to match on the
return value of the find.
This use case makes sense if you don't intend to catch Not_found, when
Not_found is a bug, period.

Le 4 avril 2012 13:38, John Carr <jfc@mit.edu> a écrit :

>
> When thinking about performance, consider the "try" keyword to take time
> to execute.  A try block pushes an exception handler onto a stack and
> pops the stack on exit.  The try block may also interfere with tail call
> optimizations.
>
> A loop like
>
>  for i = 0 to 10000000 do try ... done
>
> executes "try" 10000001 times and will run much more slowly than
>
>  try for i = 0 to 10000000 do ... done
>
> where "try" only executes once.
>
> I use options where performance matters, in frequently executed code
> where the amount of computation is not much more than the overhead of
> a try...with.  For example, I have variants of List.assoc that return
> options instead of raising exceptions.
>
> Where performance doesn't matter, i.e. the amount of code in the block
> is large or the block is rarely executed, I use exceptions or options
> based on convenience.
>
> > I benchmarked two programs, in one case the main function throw an
> exception
> > that is caught, in the other the function returns an option that is
> pattern
> > matched on.
> >
> > I noticed that, whether the exception is thrown or not, the option
> version is
> > always faster.
> >
> > Is there any case where it makes sense, performance wise, to use
> exception
> > instead of 'a option ?
>
> --
> 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
>
>

[-- Attachment #2: Type: text/html, Size: 3140 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] exn vs option
  2012-04-04 22:10   ` Julien Verlaguet
@ 2012-04-05  1:29     ` Francois Berenger
  0 siblings, 0 replies; 12+ messages in thread
From: Francois Berenger @ 2012-04-05  1:29 UTC (permalink / raw)
  To: caml-list

I think there was an article about options versus exceptions
in the OCaml journal.

If I remember well, the exceptions were faster, but I can't
find back the exact benchmark and context of this assertion.

Regards,
F.

On 04/05/2012 07:10 AM, Julien Verlaguet wrote:
> 2 more use cases:
>
> 1) When writing a deep recursion
> Throwing an exception will directly jump to your "catch" block without
> having to unfold every return call site on the stack one by one. Which
> can be much faster if the recursion is very "deep".
>
> 2) When your exception is exceptional :-)
> If Not_found is never caught, then using exceptions is faster than
> option because you don't have to allocate to perform the "find"
> operation (the difference should be minimal though).
> Plus it makes your code more readable, you don't have to match on the
> return value of the find.
> This use case makes sense if you don't intend to catch Not_found, when
> Not_found is a bug, period.
>
> Le 4 avril 2012 13:38, John Carr <jfc@mit.edu <mailto:jfc@mit.edu>> a
> écrit :
>
>
>     When thinking about performance, consider the "try" keyword to take time
>     to execute.  A try block pushes an exception handler onto a stack and
>     pops the stack on exit.  The try block may also interfere with tail call
>     optimizations.
>
>     A loop like
>
>       for i = 0 to 10000000 do try ... done
>
>     executes "try" 10000001 times and will run much more slowly than
>
>       try for i = 0 to 10000000 do ... done
>
>     where "try" only executes once.
>
>     I use options where performance matters, in frequently executed code
>     where the amount of computation is not much more than the overhead of
>     a try...with.  For example, I have variants of List.assoc that return
>     options instead of raising exceptions.
>
>     Where performance doesn't matter, i.e. the amount of code in the block
>     is large or the block is rarely executed, I use exceptions or options
>     based on convenience.
>
>      > I benchmarked two programs, in one case the main function throw
>     an exception
>      > that is caught, in the other the function returns an option that
>     is pattern
>      > matched on.
>      >
>      > I noticed that, whether the exception is thrown or not, the
>     option version is
>      > always faster.
>      >
>      > Is there any case where it makes sense, performance wise, to use
>     exception
>      > instead of 'a option ?
>
>     --
>     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
>
>


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] exn vs option
  2012-04-04 20:25 [Caml-list] exn vs option Pierre Chopin
  2012-04-04 20:38 ` John Carr
@ 2012-04-05  6:45 ` Raphael Proust
  2012-04-05  7:53   ` Benedikt Grundmann
  2012-04-05  9:05 ` Goswin von Brederlow
  2 siblings, 1 reply; 12+ messages in thread
From: Raphael Proust @ 2012-04-05  6:45 UTC (permalink / raw)
  To: Pierre Chopin; +Cc: caml-list

Aside from performance considerations, there are semantics differences
to take into account. This blog post explain why exceptions are
"better" (or, more precisely, why it is not generally a good idea to
replace exceptions by options)
http://blog.dbpatterson.com/post/9528836599 (it is in Haskell rather
than OCaml, but it still applies).

On Wed, Apr 4, 2012 at 10:25 PM, Pierre Chopin <pierre@punchup.com> wrote:
> Hi,
>
> I benchmarked two programs, in one case the main function throw an exception
> that is caught, in the other the function returns an option that is pattern
> matched on.
>
> I noticed that, whether the exception is thrown or not, the option version
> is always faster.
>
> Is there any case where it makes sense, performance wise, to use exception
> instead of 'a option ?
>
> test1.ml
> ----------------------------------------------------------------------
>
> exception Foo
> let f x =
>  if x =1 then raise Foo else ()
>
> ;;
>
>  for i = 0 to 10_000_000 do
> try
>     f 1
> with Foo -> ()
> done
> ------------------------------------------------------------------------
> test2.ml:
> ------------------------------------------------------------------------
> let f x =
>     if x=1 then None else Some ()
>
> ;;
> for i = 0 to 10_000_000 do
>     match f 1 with
>         None -> ()
>     |   Some s -> s
>     done
> ------------------------------------------------------------------------
>
>
>
> --
> Pierre Chopin,
> Chief Technology Officer and co-founder
> punchup LLC
> pierre@punchup.com
>



-- 
_______
Raphael


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] exn vs option
  2012-04-05  6:45 ` Raphael Proust
@ 2012-04-05  7:53   ` Benedikt Grundmann
  0 siblings, 0 replies; 12+ messages in thread
From: Benedikt Grundmann @ 2012-04-05  7:53 UTC (permalink / raw)
  To: Raphael Proust; +Cc: Pierre Chopin, caml-list

That post is against maybe (aka option) as an error type as it looses
information about the error.  If you use an Either type such as Core's
Result.t that argument is invalidated.

In fact at Jane Street we try avoid the use of exceptions as they don't
force the client of the library to handle the exceptional case.  Also
exceptions don't immediately imply more information one of the most wide
spread exceptions in OCaml's stdlib is Not_found which can be a nightmare
to hunt down (in particular if for whatever reason you did not also have
a backtrace).

Cheers,

Bene

On 5 April 2012 07:45, Raphael Proust <raphlalou@gmail.com> wrote:
> Aside from performance considerations, there are semantics differences
> to take into account. This blog post explain why exceptions are
> "better" (or, more precisely, why it is not generally a good idea to
> replace exceptions by options)
> http://blog.dbpatterson.com/post/9528836599 (it is in Haskell rather
> than OCaml, but it still applies).
>
> On Wed, Apr 4, 2012 at 10:25 PM, Pierre Chopin <pierre@punchup.com> wrote:
>> Hi,
>>
>> I benchmarked two programs, in one case the main function throw an exception
>> that is caught, in the other the function returns an option that is pattern
>> matched on.
>>
>> I noticed that, whether the exception is thrown or not, the option version
>> is always faster.
>>
>> Is there any case where it makes sense, performance wise, to use exception
>> instead of 'a option ?
>>
>> test1.ml
>> ----------------------------------------------------------------------
>>
>> exception Foo
>> let f x =
>>  if x =1 then raise Foo else ()
>>
>> ;;
>>
>>  for i = 0 to 10_000_000 do
>> try
>>     f 1
>> with Foo -> ()
>> done
>> ------------------------------------------------------------------------
>> test2.ml:
>> ------------------------------------------------------------------------
>> let f x =
>>     if x=1 then None else Some ()
>>
>> ;;
>> for i = 0 to 10_000_000 do
>>     match f 1 with
>>         None -> ()
>>     |   Some s -> s
>>     done
>> ------------------------------------------------------------------------
>>
>>
>>
>> --
>> Pierre Chopin,
>> Chief Technology Officer and co-founder
>> punchup LLC
>> pierre@punchup.com
>>
>
>
>
> --
> _______
> Raphael
>
>
> --
> 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
>



-- 
Calvin: I try to make everyone's day a little more
surreal.

(From Calvin & Hobbes)


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] exn vs option
  2012-04-04 20:25 [Caml-list] exn vs option Pierre Chopin
  2012-04-04 20:38 ` John Carr
  2012-04-05  6:45 ` Raphael Proust
@ 2012-04-05  9:05 ` Goswin von Brederlow
  2012-04-05  9:50   ` Daniel Bünzli
  2012-04-05 20:19   ` Pierre Chopin
  2 siblings, 2 replies; 12+ messages in thread
From: Goswin von Brederlow @ 2012-04-05  9:05 UTC (permalink / raw)
  To: Pierre Chopin; +Cc: caml-list

Pierre Chopin <pierre@punchup.com> writes:

> Hi,
>
> I benchmarked two programs, in one case the main function throw an exception
> that is caught, in the other the function returns an option that is pattern
> matched on.
>
> I noticed that, whether the exception is thrown or not, the option version is
> always faster.
>
> Is there any case where it makes sense, performance wise, to use exception
> instead of 'a option ?

I find that in most cases speed is not a major concern and then it comes
down to taste and readability of the code.

> test1.ml
> ----------------------------------------------------------------------
>
> exception Foo
> let f x =
>  if x =1 then raise Foo else ()
>
> ;;
>
>  for i = 0 to 10_000_000 do
> try
>     f 1
> with Foo -> ()
> done

0.34s user 0.01s system 99% cpu 0.351 total

That is rather short for a test. lets add 2 zeroes to the loop. And lets
call f 0 and f 1 to test both cases:

f 0: 17.72s user 0.02s system 99% cpu 17.792 total
f 1: 35.30s user 0.02s system 99% cpu 35.371 total

> ------------------------------------------------------------------------
> test2.ml:
> ------------------------------------------------------------------------
> let f x =
>     if x=1 then None else Some ()
>
> ;;
> for i = 0 to 10_000_000 do
>     match f 1 with
>         None -> ()
>     |   Some s -> s
>     done
> ------------------------------------------------------------------------

f 0: 11.60s user 0.02s system 99% cpu 11.655 total
f 1: 10.91s user 0.01s system 99% cpu 10.933 total

And lets test the speed when the exception is actualy exceptional:

exception Foo
let f x = if x =1 then raise Foo else ()

let () =
  try
    for i = 0 to 1000000000 do
      f 0
    done
  with Foo -> ()

9.94s user 0.00s system 99% cpu 9.946 total

Someone said in deep recursions exceptions are faster because they don't
have to unwind the stack:

exception Result of int
    
let rec fac acc = function
  | 1 -> raise (Result acc)
  | n -> fac (n * acc) (n - 1)
    
let () =
  for i = 0 to 100_000_000 do
    try
      fac 1 50
    with Result _ -> ()
  done

71.88s user 0.00s system 99% cpu 1:11.90 total


let rec fac acc = function
  | 1 -> acc
  | n -> fac (n * acc) (n - 1)
    
let () =
  for i = 0 to 100_000_000 do
    ignore (fac 1 50)
  done

67.04s user 0.02s system 99% cpu 1:07.08 total


Not feeling it. Lets try something not tail recursive:

exception Error
    
let rec foo = function
  | 1 -> raise Error
  | n -> n * (foo (n - 1))
    
let () =
  for i = 0 to 100_000_000 do
    try
      ignore (foo 50)
    with Error -> ()
  done

25.03s user 0.01s system 99% cpu 25.068 total

let rec foo = function
  | 1 -> None
  | n -> match foo (n - 1) with None -> None | Some x -> Some (n * x)
    
let () =
  for i = 0 to 100_000_000 do
    ignore (foo 50)
  done

49.48s user 0.01s system 99% cpu 49.508 total


In conclusion I would have to say that exceptions are better if they are
exceptional.

When you do not catch them right away or not at all then they are
better. The "try" command is more expensive than an option type and if
you are going to catch the exception right away anyway then options are
faster.

But if you don't catch them right away the cost of the try can be
amortized over many calls and becomes cheaper. Or if you don't catch the
exception at all then you can get a nice backtrace of where the
exception occured.

If your code is not tail recursive then option types mean you have to
match them on every level again and again and allocate a ton of 'Some x'
if no error occurs. You can make your code tail recursive or use
exception to improve performance there.



If you are writing a module then consider providing both flavours for
functions, one with exceptions and one with options. Even if you only do
something like this:

let find x y = ....

let raise_on_none exn f arg =
  match f arg with
  | None -> raise exn
  | Some x -> x

let find_exn x y = raise_on_none Not_found (find x) y

Obviously option only works for exceptions like Not_found. If you want
to return an error you might have to use something like

   type ('a, 'b) result = Result of 'a | Error of 'b

Putting the 2 flavours into different submodules can keep things tidy too.

MfG
        Goswin

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] exn vs option
  2012-04-05  9:05 ` Goswin von Brederlow
@ 2012-04-05  9:50   ` Daniel Bünzli
  2012-04-11 10:26     ` Goswin von Brederlow
  2012-04-05 20:19   ` Pierre Chopin
  1 sibling, 1 reply; 12+ messages in thread
From: Daniel Bünzli @ 2012-04-05  9:50 UTC (permalink / raw)
  To: caml-list

Le jeudi, 5 avril 2012 à 11:05, Goswin von Brederlow a écrit :
> If you are writing a module then consider providing both flavours for
> functions, one with exceptions and one with options. Even if you only do
> something like this:


I don't think it's a rule that should be applied consistently, I don't like libraries that provide tons of convenience functions, too many names. If you stick with the option type (or variant cases) the user can quickly wrap the function if it needs an exception (or vice-versa but I prefer it that way since it's then documented by the function signature and is in my opinion better behaved in general).

However in the particular case of finding something in a data structure where the user could be confronted with a situation where he can prove that the datum will be found I think it's justified to provide both flavours. For these cases, in my own code I settled on the following pattern :  

    val find : 'a t -> key -> 'a option
    (** [find d k] is the value bound to [k] in [d], if any. *)

    val get : 'a t -> key -> 'a  
    (** [get d k] is like {!find} but raises [Invalid_argument] if [k] is not bound in [d]. *)

Best,

Daniel

P.S. [Invalid_argument] is used for programming errors. This pattern expresses an opinion about using exceptions.  





^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] exn vs option
  2012-04-05  9:05 ` Goswin von Brederlow
  2012-04-05  9:50   ` Daniel Bünzli
@ 2012-04-05 20:19   ` Pierre Chopin
  1 sibling, 0 replies; 12+ messages in thread
From: Pierre Chopin @ 2012-04-05 20:19 UTC (permalink / raw)
  To: Goswin von Brederlow; +Cc: caml-list

[-- Attachment #1: Type: text/plain, Size: 5015 bytes --]

Thank you for your answers.
I am actually in the case of a webserver where I need to avoid interrupting
it, even in 'exceptional' cases, but rather report the problem in a log,
and return a default value whenever it is possible. Options seem to be the
best choice, not only from a safety point of view but also performance-wise.

Cheers

On Thu, Apr 5, 2012 at 5:05 AM, Goswin von Brederlow <goswin-v-b@web.de>wrote:

> Pierre Chopin <pierre@punchup.com> writes:
>
> > Hi,
> >
> > I benchmarked two programs, in one case the main function throw an
> exception
> > that is caught, in the other the function returns an option that is
> pattern
> > matched on.
> >
> > I noticed that, whether the exception is thrown or not, the option
> version is
> > always faster.
> >
> > Is there any case where it makes sense, performance wise, to use
> exception
> > instead of 'a option ?
>
> I find that in most cases speed is not a major concern and then it comes
> down to taste and readability of the code.
>
> > test1.ml
> > ----------------------------------------------------------------------
> >
> > exception Foo
> > let f x =
> >  if x =1 then raise Foo else ()
> >
> > ;;
> >
> >  for i = 0 to 10_000_000 do
> > try
> >     f 1
> > with Foo -> ()
> > done
>
> 0.34s user 0.01s system 99% cpu 0.351 total
>
> That is rather short for a test. lets add 2 zeroes to the loop. And lets
> call f 0 and f 1 to test both cases:
>
> f 0: 17.72s user 0.02s system 99% cpu 17.792 total
> f 1: 35.30s user 0.02s system 99% cpu 35.371 total
>
> > ------------------------------------------------------------------------
> > test2.ml:
> > ------------------------------------------------------------------------
> > let f x =
> >     if x=1 then None else Some ()
> >
> > ;;
> > for i = 0 to 10_000_000 do
> >     match f 1 with
> >         None -> ()
> >     |   Some s -> s
> >     done
> > ------------------------------------------------------------------------
>
> f 0: 11.60s user 0.02s system 99% cpu 11.655 total
> f 1: 10.91s user 0.01s system 99% cpu 10.933 total
>
> And lets test the speed when the exception is actualy exceptional:
>
> exception Foo
> let f x = if x =1 then raise Foo else ()
>
> let () =
>  try
>    for i = 0 to 1000000000 do
>      f 0
>    done
>  with Foo -> ()
>
> 9.94s user 0.00s system 99% cpu 9.946 total
>
> Someone said in deep recursions exceptions are faster because they don't
> have to unwind the stack:
>
> exception Result of int
>
> let rec fac acc = function
>  | 1 -> raise (Result acc)
>  | n -> fac (n * acc) (n - 1)
>
> let () =
>  for i = 0 to 100_000_000 do
>    try
>      fac 1 50
>    with Result _ -> ()
>  done
>
> 71.88s user 0.00s system 99% cpu 1:11.90 total
>
>
> let rec fac acc = function
>  | 1 -> acc
>  | n -> fac (n * acc) (n - 1)
>
> let () =
>  for i = 0 to 100_000_000 do
>    ignore (fac 1 50)
>  done
>
> 67.04s user 0.02s system 99% cpu 1:07.08 total
>
>
> Not feeling it. Lets try something not tail recursive:
>
> exception Error
>
> let rec foo = function
>  | 1 -> raise Error
>  | n -> n * (foo (n - 1))
>
> let () =
>  for i = 0 to 100_000_000 do
>    try
>      ignore (foo 50)
>    with Error -> ()
>  done
>
> 25.03s user 0.01s system 99% cpu 25.068 total
>
> let rec foo = function
>  | 1 -> None
>  | n -> match foo (n - 1) with None -> None | Some x -> Some (n * x)
>
> let () =
>  for i = 0 to 100_000_000 do
>    ignore (foo 50)
>  done
>
> 49.48s user 0.01s system 99% cpu 49.508 total
>
>
> In conclusion I would have to say that exceptions are better if they are
> exceptional.
>
> When you do not catch them right away or not at all then they are
> better. The "try" command is more expensive than an option type and if
> you are going to catch the exception right away anyway then options are
> faster.
>
> But if you don't catch them right away the cost of the try can be
> amortized over many calls and becomes cheaper. Or if you don't catch the
> exception at all then you can get a nice backtrace of where the
> exception occured.
>
> If your code is not tail recursive then option types mean you have to
> match them on every level again and again and allocate a ton of 'Some x'
> if no error occurs. You can make your code tail recursive or use
> exception to improve performance there.
>
>
>
> If you are writing a module then consider providing both flavours for
> functions, one with exceptions and one with options. Even if you only do
> something like this:
>
> let find x y = ....
>
> let raise_on_none exn f arg =
>  match f arg with
>  | None -> raise exn
>  | Some x -> x
>
> let find_exn x y = raise_on_none Not_found (find x) y
>
> Obviously option only works for exceptions like Not_found. If you want
> to return an error you might have to use something like
>
>   type ('a, 'b) result = Result of 'a | Error of 'b
>
> Putting the 2 flavours into different submodules can keep things tidy too.
>
> MfG
>         Goswin
>



-- 
Pierre Chopin,
Chief Technology Officer and co-founder
punchup LLC
pierre@punchup.com

[-- Attachment #2: Type: text/html, Size: 6492 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] exn vs option
  2012-04-05  9:50   ` Daniel Bünzli
@ 2012-04-11 10:26     ` Goswin von Brederlow
  2012-04-11 10:32       ` David House
  0 siblings, 1 reply; 12+ messages in thread
From: Goswin von Brederlow @ 2012-04-11 10:26 UTC (permalink / raw)
  To: caml-list

Daniel Bünzli <daniel.buenzli@erratique.ch> writes:

> Le jeudi, 5 avril 2012 à 11:05, Goswin von Brederlow a écrit :
>> If you are writing a module then consider providing both flavours for
>> functions, one with exceptions and one with options. Even if you only do
>> something like this:
>
>
> I don't think it's a rule that should be applied consistently, I don't like libraries that provide tons of convenience functions, too many names. If you stick with the option type (or variant cases) the user can quickly wrap the function if it needs an exception (or vice-versa but I prefer it that way since it's then documented by the function signature and is in my opinion better behaved in general).
>
> However in the particular case of finding something in a data structure where the user could be confronted with a situation where he can prove that the datum will be found I think it's justified to provide both flavours. For these cases, in my own code I settled on the following pattern :  
>
>     val find : 'a t -> key -> 'a option
>     (** [find d k] is the value bound to [k] in [d], if any. *)
>
>     val get : 'a t -> key -> 'a  
>     (** [get d k] is like {!find} but raises [Invalid_argument] if [k] is not bound in [d]. *)

That pattern works well if you have just one or few such functions and
can think of nice names to differentiate them.

Otherwise submodules are usefull:

module Foo = Foo.Options
or
module Foo = Foo.Exceptions

Foo.do_things ()

or

open Foo.Options
do_things ()

The option and exception raising functions would be named the same and
the user selects one or the other by selecting a submodule.

As said, it is usualy a matter of taste and the users tastes might
differ from the module authors taste. By providing an option and
execption flavour of a function (by different names or submodules hardly
matters) the user can use what he likes as opposed to what the modules
author imposes on him.

MfG
        Goswin

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] exn vs option
  2012-04-11 10:26     ` Goswin von Brederlow
@ 2012-04-11 10:32       ` David House
  2012-04-11 10:36         ` David House
  0 siblings, 1 reply; 12+ messages in thread
From: David House @ 2012-04-11 10:32 UTC (permalink / raw)
  To: Goswin von Brederlow; +Cc: caml-list

On Wed, Apr 11, 2012 at 11:26 AM, Goswin von Brederlow
<goswin-v-b@web.de> wrote:
>> However in the particular case of finding something in a data structure where the user could be confronted with a situation where he can prove that the datum will be found I think it's justified to provide both flavours. For these cases, in my own code I settled on the following pattern :
>>
>>     val find : 'a t -> key -> 'a option
>>     (** [find d k] is the value bound to [k] in [d], if any. *)
>>
>>     val get : 'a t -> key -> 'a
>>     (** [get d k] is like {!find} but raises [Invalid_argument] if [k] is not bound in [d]. *)
>
> That pattern works well if you have just one or few such functions and
> can think of nice names to differentiate them.

A common pattern that is convenient and clear is to append _exn to the
functions that raise excetions on failure.

This is used all over Core, and has the advantage that it is very
obvious to client code that the call may raise an exception. A call to
an _exn function without a try/with or a clearly true invariant is an
indication that you might have a bug. (Not always; sometimes the
appropriate behaviour to crash the program when some function fails.)


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] exn vs option
  2012-04-11 10:32       ` David House
@ 2012-04-11 10:36         ` David House
  0 siblings, 0 replies; 12+ messages in thread
From: David House @ 2012-04-11 10:36 UTC (permalink / raw)
  To: Goswin von Brederlow; +Cc: caml-list

On Wed, Apr 11, 2012 at 11:32 AM, David House <dhouse@janestreet.com> wrote:
> On Wed, Apr 11, 2012 at 11:26 AM, Goswin von Brederlow
> <goswin-v-b@web.de> wrote:
>>> However in the particular case of finding something in a data structure where the user could be confronted with a situation where he can prove that the datum will be found I think it's justified to provide both flavours. For these cases, in my own code I settled on the following pattern :
>>>
>>>     val find : 'a t -> key -> 'a option
>>>     (** [find d k] is the value bound to [k] in [d], if any. *)
>>>
>>>     val get : 'a t -> key -> 'a
>>>     (** [get d k] is like {!find} but raises [Invalid_argument] if [k] is not bound in [d]. *)
>>
>> That pattern works well if you have just one or few such functions and
>> can think of nice names to differentiate them.
>
> A common pattern that is convenient and clear is to append _exn to the
> functions that raise excetions on failure.

As an example, see Core's Map module:

https://bitbucket.org/yminsky/ocaml-core/src/c0e9df7b574d/base/core/lib/core_map_intf.ml

We have, e.g., [find] and [find_exn].


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2012-04-11 10:36 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-04 20:25 [Caml-list] exn vs option Pierre Chopin
2012-04-04 20:38 ` John Carr
2012-04-04 22:10   ` Julien Verlaguet
2012-04-05  1:29     ` Francois Berenger
2012-04-05  6:45 ` Raphael Proust
2012-04-05  7:53   ` Benedikt Grundmann
2012-04-05  9:05 ` Goswin von Brederlow
2012-04-05  9:50   ` Daniel Bünzli
2012-04-11 10:26     ` Goswin von Brederlow
2012-04-11 10:32       ` David House
2012-04-11 10:36         ` David House
2012-04-05 20:19   ` Pierre Chopin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).