我正在用f#编写一个简单的表达式解析器,对于每个操作符,我只想支持一定数量的操作数(例如两个用于Modulo,三个用于If)。以下是我的文件:
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"
我想摆脱或简化内部列表匹配。实现这一目标的最佳方式是什么?我应该使用多个保护符吗?
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"
但我建议将操作数的逻辑移到解析器中,这样您就可以得到一个干净的操作符表达式,这更习惯,更直接地处理,最后您将得到如下内容:
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
折叠匹配的操作数:
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"
更好的是,如果可以的话,将数据类型更改为以下类型:
type Operator =
| Modulo of string * string
| Equals of string * string
| If of string * string * string
那么在比赛中,你就不能再失败了。