如何简化这个ocaml模式匹配代码?

时间:2009-12-02 16:15:30

标签: refactoring pattern-matching ocaml

我正在编写一个简单的小型ocaml程序,它从文件中读取代数语句,使用ocamllex / ocamlyacc将其解析为AST,减少它,然后打印它。我正在减少表达的部分看起来有点......丑陋。有什么方法可以简化吗?

(* ocaml doesn't seem to be able to take arithmetic operators
 as functions, so define these wrappers for them *)
let add x y =
  x + y

let sub x y =
  x - y

let mul x y =
  x * y

let div x y =
  x / y

(* Are term1 and term2 both ints? *)
let both_ints term1 term2 =
  match (term1, term2) with
    | (Term (Number x), Term (Number y)) -> true
    | (_, _) -> false

(* We know that both terms are reducable to numbers, so combine
  them *)
let combine_terms func x y =
  match (x, y) with
      (Term (Number t1), Term (Number t2)) ->
        (Term (Number (func  t1  t2)))
    | (_, _) -> raise InvalidArg

(* Reduce the expression as much as possible *)
let rec reduce_expr expr =
  match expr with
      Plus (x, y) ->
        let reduced_x = reduce_expr x
        and reduced_y = reduce_expr y in
      if both_ints reduced_x reduced_y then
        (combine_terms add reduced_x reduced_y)
      else
        Plus (reduced_x, reduced_y)
    | Minus (x, y) ->
        let reduced_x = reduce_expr x
        and reduced_y = reduce_expr y in
      if both_ints reduced_x reduced_y then
        (combine_terms sub reduced_x reduced_y)
      else
        Minus (reduced_x, reduced_y)
    | Multiply (x, y) ->
        let reduced_x = reduce_expr x
        and reduced_y = reduce_expr y in
      if both_ints reduced_x reduced_y then
        (combine_terms mul reduced_x reduced_y)
      else
        Multiply (reduced_x, reduced_y)
    | Divide (x, y) ->
        let reduced_x = reduce_expr x
        and reduced_y = reduce_expr y in
      if both_ints reduced_x reduced_y then
        (combine_terms div reduced_x reduced_y)
      else
        Divide (reduced_x, reduced_y)
    | Term x -> Term x

1 个答案:

答案 0 :(得分:6)

您可以通过匹配操作函数中包含both_ints的类型来删除combine_termsif函数以及一些Number语句,例如:< / p>

let div x y = match x,y with
    | Number x, Number y -> Number (x / y)
    | _ -> Divide (x,y)

...
let rec reduce_expr expr = match expr with
    ...
    | Divide (x,y) -> div (reduce_expr x) (reduce_expr y)
    ...