2009-05-31 7 views
23

j'ai vu l'appel de fonction suivante dans Yacfe example:{X} avec la valeur en OCaml

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; 

Je peux voir un appel de fonction avec enregistrement initialisé comme premier argument, et ast comme second argument.

Ce que je ne suis pas familier avec la syntaxe de la forme:

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

Qu'est-ce que cela signifie? Je sais qu'un enregistrement peut être initialisé comme {name=value;name=value;...}, mais je ne connais pas le {X with name=value}, pouvez-vous me dire ce que cela signifie?

Je ne trouve pas dans le Ocaml Manual rien sur l'initialisation de la valeur d'enregistrement juridique autre que les éléments suivants:

enregistrements

6.2.3

valeurs d'enregistrement sont marqués tuples de valeurs. La valeur d'enregistrement écrite { field1 = v1; ...; fieldn = vn} associe la valeur vi à l'enregistrement champ fieldi, pour i = 1 ... n. L'implémentation actuelle prend en charge enregistrements avec jusqu'à 222 - 1 champs (champs 4194303).

Je serais heureux que dans votre réponse, vous incluiez une référence à la section appropriée dans le manuel d'OCaml.

Répondre

34

Ceci est parfois appelé "mise à jour d'enregistrement" ou "mise à jour fonctionnelle" ou quelque chose comme ça. Il évalue à un nouvel enregistrement du même type que X, et dont les champs sont initialisés à ceux de X, sauf ceux qui sont listés après le "avec", qui sont initialisés à ces valeurs données.

Il est utile pour les enregistrements immuables, comme un moyen pratique de prendre un tel enregistrement et de changer une ou deux choses sur lui (qui dans un langage impératif vous devez généralement muter les champs), sans avoir à énumérer tous les champs qui ne sont pas modifiés.

Il est décrit dans le manuel OCaml section 6.7.3, faites défiler jusqu'à "Enregistrements", deuxième paragraphe.

Pour ceux qui sont familiers avec Haskell, la syntaxe OCaml

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

est la même que la syntaxe Haskell

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

Merci. Comment pourrais-je google cela? C'est assez profond dans le manuel, et je ne pouvais pas le trouver facilement. –

+3

Je ne sais pas comment vous le feriez google. Je viens juste de le savoir. Mais en haut de cette page (section 6.7) liste la grammaire de toutes les expressions qui sont valides dans OCaml, donc si vous voulez comprendre une expression, vous pouvez commencer par là, et si vous la voyez, faites défiler la partie appropriée qui la décrit. En général, le chapitre 6 traite de divers aspects de la grammaire du langage OCaml; Il y a des sections qui traitent des expressions de type, des modèles, des classes, des modules, etc. Donc, si vous avez besoin de chercher quelque chose, je commencerais par la section appropriée. – newacct

+0

Wow, je ne savais pas que vous pouviez garder la liste 'fieldn = expern; Merci! –

14

Pour corriger la réponse précédente, le nouvel enregistrement est pas toujours de la même type que l'ancien enregistrement. Par exemple, vous pouvez avoir quelque chose comme ça:

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

En conséquence, old_t est de type string t, alors que new_t est de type int t.

Questions connexes