Records - Maple Help

Record

the record constructor

 Calling Sequence Record( a, b, ... ) Record[packed]( a, b, ... ) Record[squeezed]( a, b, ... ) Record[r1,r2]( a, b, ... ) Record[r1,r2,packed]( a, b, ... ) Record[r1,r2,squeezed]( a, b, ... ) Record[record,r1,r2]( a, b, ... )

Parameters

 a, b, ... - one or more field specifications r1, r2, ... - one or more existing records

Description

 • The record constructor Record creates a Maple record. Records are defined by their "field" names, each of which must be a Maple symbol.
 • Like an Array, a record is a fixed-size collection of items but, like a table, individual items are addressable by name rather than by a numeric offset.

Details

 • Record takes one or more field specifiers as its arguments. A field specifier is a global name, a :: expression whose first operand is a global name, or an equation whose left-hand side is one of these two. For example, each of a, a::polynom, a = 2*x, and a::polynom = 2*x is a valid field specifier.
 The name part of the specifier is the field name (a in these examples). A record having fields with the indicated names is returned. Field names cannot be repeated, and unevaluation quotes (' ') may be needed if the symbols used as field names happen to already be assigned values. If a field name has the same spelling as a local name within scope of a call to Record, then the :- prefix will be needed on the field name to force the name to be bound globally.
 An equation is used as the field specifier to indicate an initial value for the corresponding record field. For example, the field a will be assigned the value 2 if the equation a = 2 is used.
 • To make it easier to construct records programmatically, the symbol in a record field specifier may also be passed to the Record constructor as a string. This avoids potential evaluation of field names that correspond to an assigned global variable.
 • As a special case, a single record argument can be passed to Record, resulting in a copy of that record. (Note that the argument will normally need to be evaluated one level, since last-name evaluation applies to variables that have a record as a value.)
 • Records are implemented in Maple as modules, all of whose variables are exported. The field names are just the module exports. Records are distinguished from modules, in general, by the presence of the record option.

Record Inheritance

 • If the Record constructor function call is indexed, the indices must specify existing record(s). The new record will inherit all the field names of the specified records. Unlike the special case of a single record argument, indices that are variables with record values will automatically be evaluated.
 • A field specifier of the form -a will elide the specified inherited field from the record being constructed.

Packed Records

 • The Record constructor function can be called with the indexed name Record[packed], which will produce a packed record.
 • Unlike a regular record, a packed record does not create a unique instance of each field name for each record instance. When working with thousands of similar records each with many fields, this can save a significant amount of memory and processing time.
 • Fields of packed records do not exhibit last-name evaluation. That is, the expression r:-a always produces a value, even if that value is a procedure, table, Matrix, Vector, or another record.
 Similarly, it is not possible for a packed record field to have no value. The assigned function will always return true, and unassigning a packed record field will set its value to NULL instead.
 • When calling the Record constructor with one or more indices specifying existing records, the resulting record will automatically be a packed record if any of the prototype records were packed records (and none of the prototype records were squeezed records).
 • This behavior can be overridden, thus forcing the creation of non-packed records, by including the symbol record in the index of the Record constructor function.

Squeezed Records

 • The Record constructor can be called using the indexed name Record[squeezed], which will produce a squeezed record.
 • Like a packed record, a squeezed record does not create a unique instance of each field name. Furthermore, a squeezed record can squeeze multiple fields into a single underlying machine word, thus saving even more space than a packed record. How much space is occupied by a field depends on the declared type of the field:

 Declared Type Storage Used Values Allowed Default truefalse 1 bit false or true false boolean 2 bits false, true, or FAIL false integer[1] 8 bits -128 to 127 -128 integer[2] 16 bits -32768 to 32767 -32768 integer['N'..'M'] ceil(log[2](M-N+1)) N to M N identical(x1,...,xN) ceil(log[2](N)) x1, ..., or xN x1 other or no type 1 word any value 0

 The total space required for the fields of a squeezed record might exceed the sum of the storage required by each field, as fields are never split across machine words.
 • Like a packed record, fields of squeezed records always have a value. Unlike a packed record, the default value is not NULL, but the lowest possible value of the declared type.
 • When calling the Record constructor with one or more indices specifying existing records, the resulting recorded will automatically be a squeezed record if any of the prototype records were squeezed records. If any of the prototype records' fields had values not conforming to their declared type, an error will result. This behavior can be overridden by including the symbol packed or record in the index of the Record constructor.
 • Squeezed records are intended to save memory when dealing with very large numbers of records containing fields with restricted types of values. The trade-off is slightly longer access and modification time, due to the need to extract values from, or move values into, individual groups of bits.

Type Checking When Assigning to Record Fields

 • When assigning to a record field of a non-packed, non-squeezed record, the assigned value is checked to be of the declared type only if kernelopts(assertlevel) is 2.
 • Assignment to a typed field of a packed record is never checked for type correctness, as packed records were intended to maximize time efficiency.
 • Assignment to a typed field of a squeezed record is always checked if the field is of one of the squeezable types as there is no way to represent values not matching the declared type (much like it is not possible to store a string into a floating point Array). If the field is of any other type, the assignment is never checked.

Comparing and Displaying Records

 • You can use verify(...,record) to test the equality of two records. Two records are considered equal if they have the same field names, and the corresponding field values are equal.
 • Printing of records is governed by interface(max_record_depth). The setting of this interface option controls how deeply nested records are printed.

 • The Record command is thread-safe as of Maple 15.

Examples

The following statement creates a simple record r with fields a and b. Because the field names are exported, they can be accessed directly.

 > $r≔\mathrm{Record}\left('a','b'\right)$
 ${r}{≔}{\mathrm{Record}}{}\left({a}{,}{b}\right)$ (1)
 > $r:-a≔2$
 ${a}{≔}{2}$ (2)
 > $r:-a$
 ${2}$ (3)
 > $r≔\mathrm{Record}\left('a'=2x,'b'=\frac{y}{x}\right)$
 ${r}{≔}{\mathrm{Record}}{}\left({a}{=}{2}{}{x}{,}{b}{=}\frac{{y}}{{x}}\right)$ (4)
 > $\frac{r:-a}{r:-b}$
 $\frac{{2}{}{{x}}^{{2}}}{{y}}$ (5)
 > $\mathrm{type}\left(r,'\mathrm{record}'\right)$
 ${\mathrm{true}}$ (6)

Records can be combined.

 > $r≔\mathrm{Record}\left(a=1,b=2\right)$
 ${r}{≔}{\mathrm{Record}}{}\left({a}{=}{1}{,}{b}{=}{2}\right)$ (7)
 > $s≔\mathrm{Record}\left(c=3,d=4\right)$
 ${s}{≔}{\mathrm{Record}}{}\left({c}{=}{3}{,}{d}{=}{4}\right)$ (8)
 > $\mathrm{rs}≔\mathrm{Record}\left[r,s\right]\left(e=5\right)$
 ${\mathrm{rs}}{≔}{\mathrm{Record}}{}\left({a}{=}{1}{,}{b}{=}{2}{,}{c}{=}{3}{,}{d}{=}{4}{,}{e}{=}{5}\right)$ (9)
 > $\mathrm{pr}≔\mathrm{Record}\left[\mathrm{packed}\right]\left(x=24,y=25\right)$
 ${\mathrm{pr}}{≔}{{\mathrm{Record}}}_{{\mathrm{packed}}}{}\left({x}{=}{24}{,}{y}{=}{25}\right)$ (10)
 > $\mathrm{rpr}≔\mathrm{Record}\left[r,\mathrm{pr}\right]\left(z=26\right)$
 ${\mathrm{rpr}}{≔}{{\mathrm{Record}}}_{{\mathrm{packed}}}{}\left({a}{=}{1}{,}{b}{=}{2}{,}{x}{=}{24}{,}{y}{=}{25}{,}{z}{=}{26}\right)$ (11)
 > $\mathrm{sr}≔\mathrm{Record}\left[\mathrm{squeezed}\right]\left(x::'\mathrm{integer}'\left[2\right],y::\mathrm{identical}\left("a","b","c"\right)\right)$
 ${\mathrm{sr}}{≔}{{\mathrm{Record}}}_{{\mathrm{squeezed}}}{}\left({x}{::}{{\mathrm{Typesetting}}{:-}{\mathrm{_Hold}}{}\left(\left[{'}{\mathrm{integer}}{'}\right]\right)}_{{2}}{=}{-32768}{,}{y}{::}{\mathrm{identical}}{}\left({"a"}{,}{"b"}{,}{"c"}\right){=}{"a"}\right)$ (12)
 > $\mathrm{sr}:-y≔"c"$
 ${\mathrm{sr}}{:-}{y}{≔}{"c"}$ (13)
 > $\mathrm{sr}:-x≔99999$

Specified inherited fields can be elided.

 > $\mathrm{rs}≔\mathrm{Record}\left[r,s\right]\left(-b,-d\right)$
 ${\mathrm{rs}}{≔}{\mathrm{Record}}{}\left({a}{=}{1}{,}{c}{=}{3}\right)$ (14)

Records are useful for simple, structured data.

 > $\mathrm{circle}≔\mathrm{Record}\left('\mathrm{center}'=\left[0,1\right],'\mathrm{radius}'=3\right)$
 ${\mathrm{circle}}{≔}{\mathrm{Record}}{}\left({\mathrm{center}}{=}\left[{0}{,}{1}\right]{,}{\mathrm{radius}}{=}{3}\right)$ (15)
 > $\mathrm{type/circle}≔'\mathrm{record}\left(\mathrm{center},\mathrm{radius}\right)':$
 > $\mathrm{CircleArea}≔c::\mathrm{circle}↦c:-\mathrm{radius}\cdot c:-\mathrm{radius}\cdot \mathrm{\pi }:$
 > $\mathrm{CircleArea}\left(\mathrm{circle}\right)$
 ${9}{}{\mathrm{\pi }}$ (16)
 > $\mathrm{CircleCircumference}≔c::\mathrm{circle}↦2\cdot \mathrm{\pi }\cdot c:-\mathrm{radius}:$
 > $\mathrm{CircleCircumference}\left(\mathrm{circle}\right)$
 ${6}{}{\mathrm{\pi }}$ (17)

You can test the equality of two records by using a procedure such as the following. Alternatively, use the record option to verify.

 > receq := proc( a::record, b::record )     description "test whether two records are equal";     local    e;     if { exports( a ) } = { exports( b ) } then         for e in { exports( a ) } do             if a[ e ] <> b[ e ] then                 return false             end if         end do;         true     else         false     end if end proc:
 > $r≔\mathrm{Record}\left('\mathrm{foo}'=2,'\mathrm{bar}'=3\right):$
 > $s≔\mathrm{Record}\left('\mathrm{foo}'=2,'\mathrm{bar}'=4\right):$
 > $t≔\mathrm{Record}\left('\mathrm{foo}'=2,'\mathrm{bar}'=3,'\mathrm{baz}'=5\right):$
 > $\mathrm{receq}\left(r,r\right)$
 ${\mathrm{true}}$ (18)
 > $\mathrm{receq}\left(r,\mathrm{Record}\left(\mathrm{eval}\left(r,1\right)\right)\right)$
 ${\mathrm{true}}$ (19)
 > $\mathrm{receq}\left(r,s\right)$
 ${\mathrm{false}}$ (20)
 > $\mathrm{receq}\left(r,t\right)$
 ${\mathrm{false}}$ (21)
 > $\mathrm{receq}\left(s,t\right)$
 ${\mathrm{false}}$ (22)
 > $\mathrm{verify}\left(r,r,\mathrm{record}\right)$
 ${\mathrm{true}}$ (23)
 > $\mathrm{verify}\left(r,s,\mathrm{record}\right)$
 ${\mathrm{false}}$ (24)
 > $r≔\mathrm{Record}\left('\mathrm{foo}'=2,'\mathrm{bar}'=\mathrm{Record}\left('\mathrm{subfoo}'=3\right)\right)$
 ${r}{≔}{\mathrm{Record}}{}\left({\mathrm{foo}}{=}{2}{,}{\mathrm{bar}}{=}{\mathrm{Record}}{}\left({\mathrm{...}}\right)\right)$ (25)
 > $\mathrm{interface}\left(\mathrm{max_record_depth}=2\right):$
 > $\mathrm{print}\left(r\right)$
 ${\mathrm{Record}}{}\left({\mathrm{foo}}{=}{2}{,}{\mathrm{bar}}{=}{\mathrm{Record}}{}\left({\mathrm{subfoo}}{=}{3}\right)\right)$ (26)
 > $\mathrm{interface}\left(\mathrm{max_record_depth}=0\right):$
 > $\mathrm{print}\left(r\right)$
 ${\mathrm{Record}}{}\left({\mathrm{...}}\right)$ (27)

Compatibility

 • The squeezed record type was added in Maple 2020.
 • The Record command was updated in Maple 2020.