【问题标题】:Can I write OCaml pattern match with "when" in this way?我可以用这种方式用“when”编写 OCaml 模式匹配吗?
【发布时间】:2014-04-01 20:54:26
【问题描述】:

我是 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

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

【问题讨论】:

  • 关于您的更新,您的 let Set ... = i 实际上是非详尽的模式匹配,因为编译器应该警告您(即使在这种情况下您知道该模式是正确的)。触发编译器警告很少是一个好主意。在我看来,Benoît Guédas 使用as binder 给出的答案是最好的解决方案。一个小的优化可能是使用Cil.isPointerType 而不是本地定义的isPtr,但仅此而已。

标签: pattern-matching ocaml


【解决方案1】:

您可以使用带有as 关键字的别名,而不是再次解构i 以获得lve。你也可以定义一个函数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

【讨论】:

    【解决方案2】:

    您可以在when 的左侧进行进一步的模式匹配(右侧应该是boolean,因此这将不适合进一步解构元组/构造函数),

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

    【讨论】:

    • 您好,nlucaroni,谢谢您的回答,我就是这样做的……但一个问题是,在第三种模式中,我必须检查 typeOf e,其中不能直接放入任何模式(对吗?)然后我只是使用另一个匹配...在第三个模式中...足够好吗?
    • 您提供的内容是正确的。我不知道typeOf e 做了什么,也不知道e 是如何构造的以知道它是否可以直接匹配。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-18
    • 2022-11-18
    • 1970-01-01
    • 2012-12-29
    • 2011-02-24
    • 1970-01-01
    • 2021-03-12
    相关资源
    最近更新 更多