30

我在Yacfe 示例中看到了以下函数调用:

  Visitor_c.vk_program { Visitor_c.default_visitor_c with
    Visitor_c.kexpr = (fun (k, bigf) exp -> 
      match Ast_c.unwrap_expr exp with
      | Binary(e1, Logical (Eq), (((Constant(Int("0")) as _e2),_t),ii)) -> 

          (match Ast_c.get_onlytype_expr e1 with 
          | Some (qu, (Pointer _,_ii)) -> 

              let idzero = Common.tuple_of_list1 ii in
              idzero.cocci_tag := 
                Ast_cocci.MINUS (Ast_cocci.NoPos, [[null_addon]]), [];

          | _ -> k exp
          )
      | _ -> k exp
    );
  } ast;

我可以看到一个函数调用,记录初始化为第一个参数,ast第二个参数。

我不熟悉的是表单的语法:

{Visitor_c.default_visitor_c with Visitor_c.kexpr = some_value;}

这是什么意思?我知道一个记录可以初始化为{name=value;name=value;...},但我不熟悉{X with name=value},你能告诉我它是什么意思吗?

除了以下内容,我在Ocaml 手册中找不到任何关于合法记录值初始化的内容:

6.2.3 记录

记录值是标记的值元组。写入的记录值 { field1 = v1; ……;fieldn = vn } 将值 vi 与记录字段 fieldi 相关联,因为 i = 1 … n。当前实现支持多达 222 - 1 个字段(4194303 个字段)的记录。

如果在您的回答中包含对 OCaml 手册中相关部分的参考,我会很高兴。

4

2 回答 2

45

这有时被称为“记录更新”或“功能更新”或类似的东西。它评估为与 X 相同类型的新记录,并且其字段初始化为与 X 中的相同,除了“with”之后列出的那些,它们被初始化为那些给定的值。

它对于不可变的记录很有用,作为一种方便的方式来获取这样的记录并更改其中的一两件事(在命令式语言中,您通常会更改字段),而不必列出所有未更改的字段.

它在 OCaml 手册第 6.7.3 节中进行了描述,向下滚动到“记录”,第二段。

对于熟悉 Haskell 的人,OCaml 语法

{ expr with field1 = expr1 ; ... ;  fieldn = exprn }

与 Haskell 语法相同

expr { field1 = expr1 , ... ,  fieldn = exprn }
于 2009-05-31T07:38:16.267 回答
15

为了更正之前的回复,新记录并不总是与旧记录属于同一类型。例如,你可以有这样的东西:

type 'a t = {
  id : int;
  value : 'a;
}
let old_t = { id = 3; value = "foo" }
let new_t = { old_t with value = 3 }

结果,old_tis 属于 type string t,而new_tis 属于 type int t

于 2012-02-16T20:57:19.423 回答