我可以用"和#34;写OCaml模式匹配吗?通过这种方式?

时间:2014-04-01 20:54:27

标签: pattern-matching ocaml

我是OCaml的新手,这是我的原始代码:

  method vinst(i) =
  match i with
  | Set (lv , e, _) ->
       let (host, _) = lv in
        match host with
         | Mem _ -> 
          (  self#queueInstr [mkPtrLVal (addressOf lv) e];
            ChangeTo [])
         | _ -> SkipChildren
         ......

因为在Set (lv, e, _)的模式匹配之后,我仍然需要在lve上进行模式匹配,所以我想以这种方式重写它(以摆脱它烦人的开始...结束块):

     method vinst(i) =
     match i with
  | Set (lv , e, _) when (Mem _, _) = lv -> (* see I re-write it this way *)
          (  self#queueInstr [mkPtrLVal (addressOf lv) e];
            ChangeTo [])
  | Set (lv , e, _) when (Lval (Mem _, _)) = lv ->
      (  self#queueInstr [mkPtrE (addressOf lv) e];
          ChangeTo [])
  | Set (lv , e, _) when (TPtr _) = typeOf e->
        (self#queueInstr [mkPtrE (addressOf lv) e];
          ChangeTo [])
  | _ -> DoChildren

我试图编译它但是

错误:语法错误:操作符期望。

...发生

所以基本上可以这样写吗?如果是这样,我应该调整哪一部分?

==================更新===============

以下是我刚刚做的事情:

method vinst(i) =
  match i with
  | Set ((Mem _, _), e, _) -> (* pattern 1 *)
          let Set (lv, e, _) = i in
          (  self#queueInstr [mkPtrLVal (addressOf lv) e];
            ChangeTo [])
  | Set (_, Lval (Mem _, _), _) -> (* pattern 2 *)
          let Set (lv, e, _) = i in
      (  self#queueInstr [mkPtrE (addressOf lv) e];
          ChangeTo [])
  | Set (lv , e, _)   -> (* pattern 3 *)
      begin
      match typeOf e with
      | TPtr _ ->
          (self#queueInstr [mkPtrE (addressOf lv) e];
            ChangeTo [])
      | _ -> SkipChildren
    end
  | _ -> DoChildren

它够好吗?还有更优雅的方式吗?

2 个答案:

答案 0 :(得分:4)

您可以使用带有i关键字的别名,而不是再次解构lv以获取eas。您还可以定义一个函数isPtr,它返回一个布尔值,而不是直接使用typeOf

method vinst i =
  let isPtr e = match typeOf e with
    | TPtr _ -> true
    | _ -> false in
  match i with
  | Set (((Mem _, _) as lv), e, _) ->
      (  self#queueInstr [mkPtrLVal (addressOf lv) e];
        ChangeTo [])
  | Set ((_ as lv), (Lval (Mem _, _) as e), _) ->
      (  self#queueInstr [mkPtrE (addressOf lv) e];
        ChangeTo [])
  | Set (lv , e, _) when isPtr e  ->
      (  self#queueInstr [mkPtrE (addressOf lv) e];
        ChangeTo [])
  | Set (lv , e, _) -> SkipChildren
  | _ -> DoChildren

答案 1 :(得分:2)

你可以在when的左边做进一步的模式匹配(右边应该是boolean,这样就不适合进一步解构元组/构造函数了),

| Set ((Mem _,_), e, _)  ->  ...