Erlang -- Records

Erlang Reference Manual

User's Guide

Version 9.2

- User's Guide
- PDF
- Top

- Expand All
- Contract All

### Chapters

- Introduction
  - Top of chapter
  - Purpose
  - Prerequisites
  - Document Conventions
  - Complete List of BIFs
  - Reserved Words
- Character Set and Source File Encoding
  - Top of chapter
  - Character Set
  - Source File Encoding
- Data Types
  - Top of chapter
  - Terms
  - Number
  - Atom
  - Bit Strings and Binaries
  - Reference
  - Fun
  - Port Identifier
  - Pid
  - Tuple
  - Map
  - List
  - String
  - Record
  - Boolean
  - Escape Sequences
  - Type Conversions
- Pattern Matching
  - Top of chapter
  - Pattern Matching
- Modules
  - Top of chapter
  - Module Syntax
  - Module Attributes
  - Comments
  - module_info/0 and module_info/1 functions
- Functions
  - Top of chapter
  - Function Declaration Syntax
  - Function Evaluation
  - Tail recursion
  - Built-In Functions (BIFs)
- Types and Function Specifications
  - Top of chapter
  - The Erlang Type Language
  - Types and their Syntax
  - Type Declarations of User-Defined Types
  - Type Information in Record Declarations
  - Specifications for Functions
- Expressions
  - Top of chapter
  - Expression Evaluation
  - Terms
  - Variables
  - Patterns
  - Match
  - Function Calls
  - If
  - Case
  - Send
  - Receive
  - Term Comparisons
  - Arithmetic Expressions
  - Boolean Expressions
  - Short-Circuit Expressions
  - List Operations
  - Map Expressions
  - Bit Syntax Expressions
  - Fun Expressions
  - Catch and Throw
  - Try
  - Parenthesized Expressions
  - Block Expressions
  - List Comprehensions
  - Bit String Comprehensions
  - Guard Sequences
  - Operator Precedence
- Preprocessor
  - Top of chapter
  - File Inclusion
  - Defining and Using Macros
  - Predefined Macros
  - Macros Overloading
  - Flow Control in Macros
  - -error() and -warning() directives
  - Stringifying Macro Arguments
- Records
  - Top of chapter
  - Defining Records
  - Creating Records
  - Accessing Record Fields
  - Updating Records
  - Records in Guards
  - Records in Patterns
  - Nested Records
  - Internal Representation of Records
- Errors and Error Handling
  - Top of chapter
  - Terminology
  - Exceptions
  - Handling of Run-time Errors in Erlang
  - Exit Reasons
- Processes
  - Top of chapter
  - Processes
  - Process Creation
  - Registered Processes
  - Process Termination
  - Message Sending
  - Links
  - Error Handling
  - Monitors
  - Process Dictionary
- Distributed Erlang
  - Top of chapter
  - Distributed Erlang System
  - Nodes
  - Node Connections
  - epmd
  - Hidden Nodes
  - C Nodes
  - Security
  - Distribution BIFs
  - Distribution Command-Line Flags
  - Distribution Modules
- Compilation and Code Loading
  - Top of chapter
  - Compilation
  - Code Loading
  - Code Replacement
  - Running a Function When a Module is Loaded
- Ports and Port Drivers
  - Top of chapter
  - Ports
  - Port Drivers
  - Port BIFs

# 10 Records

A record is a data structure for storing a fixed number of elements. It has named fields and is similar to a struct in C. Record expressions are translated to tuple expressions during compilation. Therefore, record expressions are not understood by the shell unless special actions are taken. For details, see the shell(3) manual page in STDLIB.

More examples are provided in Programming Examples.

### 10.1 Defining Records

A record definition consists of the name of the record, followed by the field names of the record. Record and field names must be atoms. Each field can be given an optional default value. If no default value is supplied, undefined is used.

    -record(Name, {Field1 [= Value1],
                   ...
                   FieldN [= ValueN]}).

A record definition can be placed anywhere among the attributes and function declarations of a module, but the definition must come before any usage of the record.

If a record is used in several modules, it is recommended that the record definition is placed in an include file.

### 10.2 Creating Records

The following expression creates a new Name record where the value of each field FieldI is the value of evaluating the corresponding expression ExprI:

    #Name{Field1=Expr1,...,FieldK=ExprK}

The fields can be in any order, not necessarily the same order as in the record definition, and fields can be omitted. Omitted fields get their respective default value instead.

If several fields are to be assigned the same value, the following construction can be used:

    #Name{Field1=Expr1,...,FieldK=ExprK, _=ExprL}

Omitted fields then get the value of evaluating ExprL instead of their default values. This feature is primarily intended to be used to create patterns for ETS and Mnesia match functions.

Example:

    -record(person, {name, phone, address}).

    ...

    lookup(Name, Tab) ->
        ets:match_object(Tab, #person{name=Name, _='_'}).

### 10.3 Accessing Record Fields

    Expr#Name.Field

Returns the value of the specified field. Expr is to evaluate to a Name record.

The following expression returns the position of the specified field in the tuple representation of the record:

    #Name.Field

Example:

    -record(person, {name, phone, address}).

    ...

    lookup(Name, List) ->
        lists:keysearch(Name, #person.name, List).

### 10.4 Updating Records

    Expr#Name{Field1=Expr1,...,FieldK=ExprK}

Expr is to evaluate to a Name record. A copy of this record is returned, with the value of each specified field FieldI changed to the value of evaluating the corresponding expression ExprI. All other fields retain their old values.

### 10.5 Records in Guards

Since record expressions are expanded to tuple expressions, creating records and accessing record fields are allowed in guards. However all subexpressions, for example, for field initiations, must be valid guard expressions as well.

Examples:

    handle(Msg, State) when Msg==#msg{to=void, no=3} ->
        ...

    handle(Msg, State) when State#state.running==true ->
        ...

There is also a type test BIF is_record(Term, RecordTag).

Example:

    is_person(P) when is_record(P, person) ->
        true;
    is_person(_P) ->
        false.

### 10.6 Records in Patterns

A pattern that matches a certain record is created in the same way as a record is created:

    #Name{Field1=Expr1,...,FieldK=ExprK}

In this case, one or more of Expr1...ExprK can be unbound variables.

### 10.7 Nested Records

Beginning with Erlang/OTP R14, parentheses when accessing or updating nested records can be omitted. Assume the following record definitions:

    -record(nrec0, {name = "nested0"}).
    -record(nrec1, {name = "nested1", nrec0=#nrec0{}}).
    -record(nrec2, {name = "nested2", nrec1=#nrec1{}}).

    N2 = #nrec2{},

Before R14, parentheses were needed as follows:

    "nested0" = ((N2#nrec2.nrec1)#nrec1.nrec0)#nrec0.name,
    N0n = ((N2#nrec2.nrec1)#nrec1.nrec0)#nrec0{name = "nested0a"},

Since R14, the following can also be written:

    "nested0" = N2#nrec2.nrec1#nrec1.nrec0#nrec0.name,
    N0n = N2#nrec2.nrec1#nrec1.nrec0#nrec0{name = "nested0a"},

### 10.8 Internal Representation of Records

Record expressions are translated to tuple expressions during compilation. A record defined as:

    -record(Name, {Field1,...,FieldN}).

is internally represented by the tuple:

    {Name,Value1,...,ValueN}

Here each ValueI is the default value for FieldI.

To each module using records, a pseudo function is added during compilation to obtain information about records:

    record_info(fields, Record) -> [Field]
    record_info(size, Record) -> Size

Size is the size of the tuple representation, that is, one more than the number of fields.

In addition, #Record.Name returns the index in the tuple representation of Name of the record Record.

Name must be an atom.