开发者

How to change a part of values in a record?

开发者 https://www.devze.com 2023-03-17 05:47 出处:网络
I have defined a type like that: type s_program = { globals : s_var list; main: s_block; } and s_var = { s_var_name: string;

I have defined a type like that:

type s_program =
    { globals : s_var list;
      main: s_block; }
and s_var =
    { s_var_name: string;
      s_var_type: s_type;
     开发者_StackOverflow s_var_uniqueId: s_uniqueId }
and s_uniqueId = int

At a point of my program, i have a variable p: s_program, but I need to change s_var_uniqueId of every element of p.globals, for instance, add 1 to every s_var_uniqueId. I have some questions:

1) May I modify directly the related values in p, or do I have to assign new values to a new p':s_program

2) May I write something like that:

let p' = 
  { p with 
     globals = List.map (fun var -> { var with s_var_uniqueId = var.s_var_uniqueId + 1 }) p.globals

Thank you very much.

Edit 1: correct with part as suggested


First you may want to read this section on record in OCaml and this chapter on modifiable data structures. As stated, you will see that records are not mutable. Second, you need to think about what you really want : mutable record, record with mutable fields or mutable record with mutable fields. For example suppose that we have a record for complex numbers (this is the same example in ref 1).

type complex = { re:float; im:float } ;;

If you declare something like

let c = {re=2.;im=3.} ;;

then you cannot change neither c nor re (or im). Indeed c := {re=4.;im=6.} ;; or c.re := 4.;; will both failed with an error. To get a mutable record, you just have to use a reference for c.

let c = ref {re=2.;im=3.} ;;

Then you can change c with c := {re=4.;im=6.} ;;. But I think that you want to have mutable field ! Then you have to precise which fields are mutables. Suppose that you want all fields to be mutable you can write

type complex = { re:float ref; im:float ref }
let make_complex r i = { re = ref r ; im = ref i } 
let c = make_complex 3. 4.
;;

and then change fields with

c.re := 6. ; c.im := 7. ;;

It would be easier with a function of type float -> float -> ()

let change_re c r = c.re := r ;;
let change_im c i = c.im := i ;;
let change_complex c r i = change_re c r ; change_im c i ;;

However, I will suggest you to really think about bringing imperative feature like this in your code. This could be a simple way to completly wreck its readibility.


1) That depends whether you want to use Ocaml as an imperative or functional programming language :). If it's the former, you can make both fields of the records mutable (by adding mutable keyword before field name) and then change them in place. However I'd strongly advice not to do that and to:

2) go with your second approach, which looks perfectly fine (except that you seem to be missing {...} for the second record modification.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号