【问题标题】:How can I simplify this ocaml pattern-matching code?如何简化此 ocaml 模式匹配代码?
【发布时间】:2009-12-02 16:15:29
【问题描述】:

我正在编写一个简单的小 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

【问题讨论】:

  • 请注意,ocaml 确实将算术运算符作为函数:使用 ( / )、( + ) ( * ) 和 ( - )... () 是必需的,空格仅对 *
  • 只是为了解析,menhir 值得考虑。 cristal.inria.fr/~fpottier/menhir
  • 其实我一直在使用 ocamlyacc 并且我通常会使用 menhir,但我想保持简单的依赖关系。

标签: refactoring pattern-matching ocaml


【解决方案1】:

您可以删除both_intscombine_terms函数以及一些if语句,通过匹配操作函数中包含Number的类型,例如:

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)
    ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多