I could do this easily in C++ (note: I didn't test this for correctness--it's only to illustrate what I'm trying to do):
const int BadParam = -1;
const int Success = 0;
int MyFunc(int param)
{
if(param < 0)
{
return BadParam;
}
//normal processing
return Success;
}
But I cannot figure out how to exit a routine early in F#. What I want to do is to exit the function on a bad input but continue if the input is ok. Am I missing some fundamental property of F# or am I approaching the problem in the wrong way since I'm just learning FP? Is a failwith my only option here?
This is what I've got so far and it compiles ok:
#light
module test1
(* Define how many arguments we're expecting *)
let maxArgs = 2;;
(* The indices of the various arguments on the command line *)
type ProgArguments =
| SearchString = 0
| FileSpec = 1;;
(* Various errorlevels which the app can return and what they indicate *)
type ProgReturn =
| Success = 0
| WrongNumberOfArgumentsPassed = 1;;
[<EntryPoint>]
let main (args:string[]) =
printfn "args.Length is %d" args.Length
let ProgExitCode = if args.Length <> maxArgs then
printfn "Two arguments must be passed"
int ProgReturn.WrongNumberOfArgumentsPassed
(* Want to exit "main" here but how? *)
else
int ProgReturn.Success
let searchstring, filespec = args.[int ProgArguments.SearchString],args.[int ProgArguments.FileSpec];
printfn "searchstring is %s" searchstring
printfn "filespec is %s" filespec
ProgExitCode;;
Is there an FP way of dealing with this sort of thing?
In my opinion, match expressions are the F# analogue of early-exit for calling out erroneous conditions and handling them separately. For your example, I'd write:
[<EntryPoint>]
let main (args:string[]) =
printfn "args.Length is %d" args.Length
match args with
| [| searchstring; filespace |] ->
// much code here ...
int Success
| _ -> printfn "Two arguments must be passed"
int WrongNumberOfArgumentsPassed
This separates the error case nicely. In general, if you need to exit from the middle of something, split functions and then put the error case in a match
. There's really no limit to how small functions should be in a functional language.
As an aside, your use of discriminated unions as sets of integer constants is a little weird. If you like that idiom, be aware that you don't need to include the type name when referring to them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With