ocaml 中的 {X with value}

发布于 2024-07-22 20:39:03 字数 1444 浏览 3 评论 0原文

我在 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 记录

记录值被标记为元组 价值观。 写入的记录值{ 字段1 = v1; ……; 场 n = vn } 将值 vi 与记录关联 字段 fieldi,对于 i = 1 … n。 这 当前的实现支持 最多 222 − 1 个字段的记录 (4194303 个字段)。

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

I saw the following function call in Yacfe example:

  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;

I can see a function call with record initialized as the first argument, and ast as the second argument.

What I'm not familiar with is the syntax of the form:

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

What does this means? I know a record can be initialized like {name=value;name=value;...}, but I'm not familiar with the {X with name=value}, can you tell me what it means?

I can't find in the Ocaml Manual nothing about legal record value initialization other than the following:

6.2.3 Records

Record values are labeled tuples of
values. The record value written {
field1 = v1; …; fieldn = vn }
associates the value vi to the record
field fieldi, for i = 1 … n. The
current implementation supports
records with up to 222 − 1 fields
(4194303 fields).

I'll be glad if in your answer you'll include a reference to the relevant section in the OCaml manual.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

堇色安年 2024-07-29 20:39:03

这有时称为“记录更新”或“功能更新”或类似的名称。 它计算出与 X 类型相同的新记录,其字段初始化为与 X 中的字段相同,但“with”后面列出的字段除外,这些字段被初始化为给定值。

它对于不可变记录很有用,作为一种获取此类记录并更改其上的一两个内容的便捷方法(在命令式语言中,您通常会改变字段),而不必列出所有未更改的字段。

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

对于熟悉 Haskell 的人来说,OCaml 语法

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

与 Haskell 语法相同

expr { field1 = expr1 , ... ,  fieldn = exprn }

This is sometimes called a "record update" or "functional update" or something like that. It evaluates to a new record of the same type as X, and whose fields are initialized to the same as those in X, except the ones which are listed after the "with", which are initialized to those given values.

It is useful for immutable records, as a convenient way to take such a record and change one or two things on it (which in an imperative language you would typically mutate the fields), without having to list out all the fields that are not changed.

It is described in the OCaml manual section 6.7.3, scroll down to "Records", second paragraph.

For those who are familiar with Haskell, the OCaml syntax

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

is the same as the Haskell syntax

expr { field1 = expr1 , ... ,  fieldn = exprn }
你好,陌生人 2024-07-29 20:39:03

为了更正之前的回复,新记录并不总是与旧记录具有相同的类型。
例如,您可以有类似的

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

结果:old_t 的类型为 string t,而 new_t 的类型为 int t

To correct the previous reply, the new record is not always of the same type as the old record.
For example, you can have something like that:

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

As a result, old_t is of type string t, while new_t is of type int t.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文