Record
the record constructor
Calling Sequence
Parameters
Description
Details
Record Inheritance
Packed Records
Squeezed Records
Type Checking When Assigning to Record Fields
Comparing and Displaying Records
Thread Safety
Examples
Compatibility
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, ... )
a, b, ...
-
one or more field specifications
r1, r2, ...
one or more existing records
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.
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.
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.
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.
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
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.
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.
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.
For more information on thread safety, see index/threadsafe.
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≔Record⁡a,b
r:-a≔2
a≔2
r:-a
2
r≔Record⁡a=2⁢x,b=yx
r:-ar:-b
2⁢x2y
type⁡r,record
true
Records can be combined.
r≔Record⁡a=1,b=2
s≔Record⁡c=3,d=4
rs≔Recordr,s⁡e=5
rs≔Record⁡a=1,b=2,c=3,d=4,e=5
pr≔Recordpacked⁡x=24,y=25
rpr≔Recordr,pr⁡z=26
rpr≔Recordpacked⁡a=1,b=2,x=24,y=25,z=26
sr≔Recordsqueezed⁡x::integer2,y::identical⁡a,b,c
sr≔Recordsqueezed⁡x::ℤ2=−32768,y::identical⁡a,b,c=a
sr:-y≔c
sr:−y≔c
sr:-x≔99999
Error, unable to store 99999 in squeezed record field `x` of type integer[2]
Specified inherited fields can be elided.
rs≔Recordr,s⁡−b,−d
rs≔Record⁡a=1,c=3
Records are useful for simple, structured data.
circle≔Record⁡center=0,1,radius=3
`type/circle`≔record⁡center,radius:
CircleArea≔c::circle↦c:−radius⋅c:−radius⋅π:
CircleArea⁡circle
9⁢π
CircleCircumference≔c::circle↦2⋅π⋅c:−radius:
CircleCircumference⁡circle
6⁢π
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≔Record⁡foo=2,bar=3:
s≔Record⁡foo=2,bar=4:
t≔Record⁡foo=2,bar=3,baz=5:
receq⁡r,r
receq⁡r,Record⁡eval⁡r,1
receq⁡r,s
receq⁡r,t
receq⁡s,t
verify⁡r,r,record
verify⁡r,s,record
r≔Record⁡foo=2,bar=Record⁡subfoo=3
r≔Record⁡foo=2,bar=Record⁡...
interface⁡max_record_depth=2:
print⁡r
Record⁡foo=2,bar=Record⁡subfoo=3
interface⁡max_record_depth=0:
Record⁡...
The squeezed record type was added in Maple 2020.
The Record command was updated in Maple 2020.
See Also
Array
interface
list
module
symbol
table
type/record
verify/record
Download Help Document