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;

最初の引数と 2 番目の引数としてレコードが初期化された関数呼び出しを確認でき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 } は、i = 1 … n の場合、値 vi をレコード フィールド fieldi に関連付けます。現在の実装では、最大 222 − 1 フィールド (4194303 フィールド) のレコードがサポートされています。

OCamlマニュアルの関連セクションへの参照を回答に含めていただければ幸いです。

4

2 に答える 2

45

これは、「レコード更新」または「機能更新」などと呼ばれることもあります。Xと同じタイプの新しいレコードに評価され、そのフィールドはXのフィールドと同じに初期化されます。ただし、「with」の後にリストされているものは、指定された値に初期化されます。

変更されていないすべてのフィールドをリストする必要なしに、そのようなレコードを取得してそのレコードの1つまたは2つを変更する便利な方法(命令型言語では通常フィールドを変更する)として、不変のレコードに役立ちます。 。

これはOCamlマニュアルのセクション6.7.3で説明されており、「レコード」の2番目の段落までスクロールダウンします。

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_tは 型string tであり、new_tは 型int tです。

于 2012-02-16T20:57:19.423 に答える