views:

87

answers:

4

Hello,

I'm trying to write a function where only two method calls (with the methods being unit -> unit) should have a certain exception handled. The behaviour should be:
- if an exception is raised the entire function ends
- the function goes on (outside of the exception handler) otherwise

At first I thought I could use a function with the statements wrapped in a try/with block and a continuation, but of course the continuation would be called from within the block...I could probably wrap the statements in a function and use a return value to signal success/failure, however that looks clunky to me compared to the following C# code, which does what I'm trying to achieve in F#.

SomeType MyMethod(string x)
{
    ...
    try
    {
        foo();
        bar();
    }
    catch(SomeException)
    {
        return null;
    }
    ...
    return ...;
}
+4  A: 

Something like this?

// f <- foo(); bar(); etc...
// k <- unprotected continuation
let runProtected f k = 
    if try f(); true with _ -> false 
    then k()
    else null

// sample from the question 
let runProtected () = 
    if try 
        foo(); bar();
        true 
       with _ -> 
        false 
    then unprotected()
    else null
desco
I think this is as close as I can get to what I would like to do, although I think in this situation lacking the greater control over the control flow of imperative programming is a handicap.
emaster70
A: 

How about:

let success =
    try
        foo ()
        bar ()
        true
    with :? SomeException ->
        false

if success then
    ...
else
    ()
Tim Robinson
+2  A: 

I think best idiomatic code is using an option type:

member t.MyMethod(x : string) : SomeType =
    let result =
        try
            foo()
            bar()
            Some(...)
        with :? SomeException ->
            None

    match(result)
    | Some(...) -> // do other work and return something
    | None -> // return something
Stringer Bell
That's what I thought of when I wrote "I could probably wrap the statements in a function and use a return value to signal success/failure". Doesn't really look awesome (to me) nor too effective, but I have to recognize it's ideomatic. +1 :)
emaster70
A: 

Well... you could do...

type Test() =
    member this.MyMethod (x:string) =
        if try
            foo()
            bar()
            true
           with _ -> false
        then
            // do more work
            "blah"
        else
            null

Or, flip the true/false...

type Test() =
    member this.MyMethod (x:string) =
        if try
            foo();
            bar();
            false
           with _ -> true
        then
            // bail early
            null
        else
            // do more work
            "blah"

Highly recommend switching from returning null to returning an option type (Some(x)/None), though. Let the compiler catch places where null isn't handled, rather than your users ;-)

James Hugard