Previous: Accessing Fields Using $, Up: Records



3.11.4 Record Assignment

You can assign one record value to another using simple assignment:

         local a: conn_id;
         ...
         local b: conn_id;
         ...
         b = a;

Doing so produces a shallow copy. That is, after the assignment, b refers to the same record as does a, and an assignment to one of b's fields will alter the field in a's value (and vice versa for an assignment to one of a's fields). However, assigning again to b itself, or assigning to a itself, will break the connection.

In order to produce a deep copy, use the clone operator “copy()”. For more details, see Expressions.

You can also assign to a record another record that has fields with the same names and types, even if they come in a different order. For example, if you have:

         local b: conn_id;
         local c: record {
             resp_h: addr, orig_h: addr;
             resp_p: port, orig_p: port;
         };

then you can assign either b to c or vice versa.

You could not, however, make the assignment (in either direction) if you had:

         local b: conn_id;
         local c: record {
             resp_h: addr, orig_h: addr;
             resp_p: port, orig_p: port;
             num_notices: count;
         };

because the field num_notices would either be missing or excess.

However, when declaring a record you can associate attributes with the fields. The relevant ones are &optional, which indicates that when assigning to the record you can omit the field, and &default = expr, which indicates that if the field is missing, then a reference to it returns the value of the expression expr. So if instead you had:

         local b: conn_id;
         local c: record {
             resp_h: addr, orig_h: addr;
             resp_p: port, orig_p: port;
             num_notices: count &optional;
         };

then you could execute c = b even though num_notices is missing from b. You still could not execute b = c, though, since in that direction, num_notices is an extra field (regardless of whether it has been assigned to or not — the error is a type-checking error, not a run-time error).

The same holds for:

         local b: conn_id;
         local c: record {
             resp_h: addr, orig_h: addr;
             resp_p: port, orig_p: port;
             num_notices: count &default = 0;
         };

I.e., you could execute c = b but not b = c. The only difference between this example and the previous one is that for the previous one, access to c$num_notices without having first assigned to it results in a run-time error, while in the second, it yields 0.

You can test for whether a record field exists using the ?$ operator.

Finally, all of the rules for assigning records also apply when passing a record value as an argument in a function call or an event handler invocation.