2010-07-12 2 views
3

J'essaye d'écrire une fonction où seulement deux appels de méthode (avec les méthodes étant unit -> unit) devraient avoir une certaine exception gérée. Le comportement doit être:
- si une exception est levée toute la fonction se termine
- la fonction continue (en dehors du gestionnaire d'exceptions), sinon

Au début, je pensais que je pouvais utiliser une fonction avec les états enveloppées dans un essai/avec un bloc et une continuation, mais bien sûr la continuation serait appelée depuis le bloc ... Je pourrais probablement envelopper les instructions dans une fonction et utiliser une valeur de retour pour signaler le succès/l'échec, mais cela semble maladroit à moi comparé au code C# suivant, qui fait ce que j'essaye de réaliser en F #.

F # Gestion des exceptions pour une partie de la fonction

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

Répondre

4

Quelque chose comme ça?

// 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 
+0

Je pense que ceci est aussi proche que je peux obtenir à ce que je voudrais faire, bien que je pense que dans cette situation manquant le plus grand contrôle sur le flux de contrôle de la programmation impérative est un handicap. – em70

0

Que diriez-vous:

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

if success then 
    ... 
else 
    () 
2

Je pense que le code mieux idiomatiques utilise un type d'option:

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 
+0

C'est ce que j'ai pensé quand j'ai écrit "Je pourrais probablement envelopper les instructions dans une fonction et utiliser une valeur de retour pour signaler le succès/l'échec". Ça ne me semble pas vraiment génial (pas très efficace), mais je dois reconnaître que c'est idiot. +1 :) – em70

0

Eh bien ... vous pouvez faire ...

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

Ou, fl ip le vrai/faux ...

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

recommande vivement le passage de retour null pour retourner un type d'option (Certains (x)/Aucune), cependant. Laissez le compilateur attraper les endroits où null n'est pas manipulé, plutôt que vos utilisateurs ;-)