Reputation: 1174
I am writing a simple expressions parser in F# and for each operator I want only to support a certain number of operands (e.g. two for Modulo, three for If). Here is what I have:
type Operator =
| Modulo
| Equals
| If
let processOperator operands operator =
match operator with
| Modulo ->
match operands with
| [ a:string; b:string ] -> (Convert.ToInt32(a) % Convert.ToInt32(b)).ToString()
| _ -> failwith "wrong number of operands"
| Equals ->
match operands with
| [ a; b ] -> (a = b).ToString()
| _ -> failwith "wrong operands"
| If ->
match operands with
| [ a; b; c ] -> (if Convert.ToBoolean(a) then b else c).ToString()
| _ -> failwith "wrong operands"
I would like to get rid of or simplify the inner list matches. What is the best way to accomplish this? Should I use multiple guards ?
Upvotes: 1
Views: 418
Reputation: 26174
open System
type Operator =
| Modulo
| Equals
| If
let processOperator operands operator =
match (operator, operands) with
| Modulo, [a: string; b] -> string ((int a) % (int b))
| Equals, [a; b] -> string (a = b)
| If, [a; b; c] -> if Convert.ToBoolean(a) then b else c
| _ -> failwith "wrong number of operands"
But I would suggest to move this logic of the operands to the parser, this way you get a clean operator expression, which is more idiomatic and straight forward to process, at the end you'll have something like this:
open System
type Operator =
| Modulo of int * int
| Equals of int * int
| If of bool * string * string
let processOperator = function
| Modulo (a, b) -> string (a % b)
| Equals (a, b) -> string (a = b)
| If (a, b, c) -> if a then b else c
Upvotes: 4
Reputation: 5688
Fold in the operands matching:
let processOperator operands operator =
match operator, operands with
| Modulo, [a; b] -> (Convert.ToInt32(a) % Convert.ToInt32(b)).ToString()
| Equals, [a; b] -> (a = b).ToString()
| If, [ a; b; c ] -> (if Convert.ToBoolean(a) then b else c).ToString()
| _ -> failwith "wrong number of operands"
Better yet, if you can, change the datatype to the following.
type Operator =
| Modulo of string * string
| Equals of string * string
| If of string * string * string
Then in the match, you can no longer fail.
Upvotes: 3