Sophie

Sophie

distrib > Fedora > 17 > i386 > media > updates > by-pkgid > 675c8c8167236dfcf8d66da674f931e8 > files > 106

erlang-doc-R15B-03.3.fc17.noarch.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html xmlns:fn="http://www.w3.org/2005/02/xpath-functions">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="../otp_doc.css" type="text/css">
<title>Erlang -- Records</title>
</head>
<body bgcolor="white" text="#000000" link="#0000ff" vlink="#ff00ff" alink="#ff0000"><div id="container">
<script id="js" type="text/javascript" language="JavaScript" src="../js/flipmenu/flipmenu.js"></script><script id="js2" type="text/javascript" src="../js/erlresolvelinks.js"></script><script language="JavaScript" type="text/javascript">
            <!--
              function getWinHeight() {
                var myHeight = 0;
                if( typeof( window.innerHeight ) == 'number' ) {
                  //Non-IE
                  myHeight = window.innerHeight;
                } else if( document.documentElement && ( document.documentElement.clientWidth ||
                                                         document.documentElement.clientHeight ) ) {
                  //IE 6+ in 'standards compliant mode'
                  myHeight = document.documentElement.clientHeight;
                } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
                  //IE 4 compatible
                  myHeight = document.body.clientHeight;
                }
                return myHeight;
              }

              function setscrollpos() {
                var objf=document.getElementById('loadscrollpos');
                 document.getElementById("leftnav").scrollTop = objf.offsetTop - getWinHeight()/2;
              }

              function addEvent(obj, evType, fn){
                if (obj.addEventListener){
                obj.addEventListener(evType, fn, true);
                return true;
              } else if (obj.attachEvent){
                var r = obj.attachEvent("on"+evType, fn);
                return r;
              } else {
                return false;
              }
             }

             addEvent(window, 'load', setscrollpos);

             //--></script><div id="leftnav"><div class="innertube">
<img alt="Erlang logo" src="../erlang-logo.png"><br><small><a href="users_guide.html">User's Guide</a><br><a href="../pdf/otp-system-documentation-5.9.3.1.pdf">PDF</a><br><a href="../index.html">Top</a></small><p><strong>Programming Examples</strong><br><strong>User's Guide</strong><br><small>Version 5.9.3.1</small></p>
<br><a href="javascript:openAllFlips()">Expand All</a><br><a href="javascript:closeAllFlips()">Contract All</a><p><small><strong>Chapters</strong></small></p>
<ul class="flipMenu" imagepath="../js/flipmenu">
<li id="loadscrollpos" title="Records" expanded="true">Records<ul>
<li><a href="records.html">
              Top of chapter
            </a></li>
<li title="Records vs Tuples"><a href="records.html#id60765">Records vs Tuples</a></li>
<li title="Defining a Record"><a href="records.html#id60728">Defining a Record</a></li>
<li title="Creating a Record"><a href="records.html#id59920">Creating a Record</a></li>
<li title="Accessing a Record Field"><a href="records.html#id60048">Accessing a Record Field</a></li>
<li title="Updating a Record"><a href="records.html#id61983">Updating a Record</a></li>
<li title="Type Testing"><a href="records.html#id60031">Type Testing</a></li>
<li title="Pattern Matching"><a href="records.html#id60080">Pattern Matching</a></li>
<li title="Nested Records"><a href="records.html#id61405">Nested Records</a></li>
<li title="Example"><a href="records.html#id57989">Example</a></li>
</ul>
</li>
<li id="no" title="Funs" expanded="false">Funs<ul>
<li><a href="funs.html">
              Top of chapter
            </a></li>
<li title="Example 1 - map"><a href="funs.html#id64362">Example 1 - map</a></li>
<li title="Example 2 - foreach"><a href="funs.html#id57513">Example 2 - foreach</a></li>
<li title="The Syntax of Funs"><a href="funs.html#id61441">The Syntax of Funs</a></li>
<li title="Variable Bindings Within a Fun"><a href="funs.html#id61096">Variable Bindings Within a Fun</a></li>
<li title="Funs and the Module Lists"><a href="funs.html#id61883">Funs and the Module Lists</a></li>
<li title="Funs Which Return Funs"><a href="funs.html#id62549">Funs Which Return Funs</a></li>
</ul>
</li>
<li id="no" title="List Comprehensions" expanded="false">List Comprehensions<ul>
<li><a href="list_comprehensions.html">
              Top of chapter
            </a></li>
<li title="Simple Examples"><a href="list_comprehensions.html#id63964">Simple Examples</a></li>
<li title="Quick Sort"><a href="list_comprehensions.html#id64034">Quick Sort</a></li>
<li title="Permutations"><a href="list_comprehensions.html#id64089">Permutations</a></li>
<li title="Pythagorean Triplets"><a href="list_comprehensions.html#id64141">Pythagorean Triplets</a></li>
<li title="Simplifications with List Comprehensions"><a href="list_comprehensions.html#id64218">Simplifications with List Comprehensions</a></li>
<li title="Variable Bindings in List Comprehensions"><a href="list_comprehensions.html#id64241">Variable Bindings in List Comprehensions</a></li>
</ul>
</li>
<li id="no" title="Bit Syntax" expanded="false">Bit Syntax<ul>
<li><a href="bit_syntax.html">
              Top of chapter
            </a></li>
<li title="Introduction"><a href="bit_syntax.html#id64741">Introduction</a></li>
<li title="A Lexical Note"><a href="bit_syntax.html#id65026">A Lexical Note</a></li>
<li title="Segments"><a href="bit_syntax.html#id65049">Segments</a></li>
<li title="Defaults"><a href="bit_syntax.html#id65237">Defaults</a></li>
<li title="Constructing Binaries and Bitstrings"><a href="bit_syntax.html#id65297">Constructing Binaries and Bitstrings</a></li>
<li title="Matching Binaries"><a href="bit_syntax.html#id65485">Matching Binaries</a></li>
<li title="Appending to a Binary"><a href="bit_syntax.html#id65619">Appending to a Binary</a></li>
</ul>
</li>
</ul>
</div></div>
<div id="content">
<div class="innertube">
<h1>1 Records</h1>
  

  <h3><a name="id60765">1.1 
        Records vs Tuples</a></h3>
    
    <p>The main advantage of using records instead of tuples is that
      fields in a record are accessed by name, whereas fields in a
      tuple are accessed by position. To illustrate these differences,
      suppose that we want to represent a person with the tuple
      <span class="code">{Name, Address, Phone}</span>.</p>
    <p>We must remember that the <span class="code">Name</span> field is the first
      element of the tuple, the <span class="code">Address</span> field is the second
      element, and so on, in order to write functions which manipulate
      this data. For example, to extract data from a variable <span class="code">P</span>
      which contains such a tuple we might write the following code
      and then use pattern matching to extract the relevant fields.</p>
    <div class="example"><pre>
Name = element(1, P),
Address = element(2, P),
...</pre></div>
    <p>Code like this is difficult to read and understand and errors
      occur if we get the numbering of the elements in the tuple wrong.
      If we change the data representation by re-ordering the fields,
      or by adding or removing a field, then all references to
      the person tuple, wherever they occur, must be checked and
      possibly modified.</p>
    <p>Records allow us to refer to the fields by name and not
      position. We use a record instead of a tuple to store the data.
      If we write a record definition of the type shown below, we can
      then refer to the fields of the record by name.</p>
    <div class="example"><pre>
-record(person, {name, phone, address}).</pre></div>
    <p>For example, if <span class="code">P</span> is now a variable whose value is a
      <span class="code">person</span> record, we can code as follows in order to access
      the name and address fields of the records.</p>
    <div class="example"><pre>
Name = P#person.name,
Address = P#person.address,
...</pre></div>
    <p>Internally, records are represented using tagged tuples:</p>
    <div class="example"><pre>
{person, Name, Phone, Address}</pre></div>
  

  <h3><a name="id60728">1.2 
        Defining a Record</a></h3>
    
    <p>This definition of a person will be used in many of
      the examples which follow. It contains three fields, <span class="code">name</span>,
      <span class="code">phone</span> and <span class="code">address</span>. The default values for
      <span class="code">name</span> and <span class="code">phone</span> is "" and [], respectively.
      The default value for <span class="code">address</span> is the atom
      <span class="code">undefined</span>, since no default value is supplied for this
      field:</p>
    <div class="example"><pre>
-record(person, {name = "", phone = [], address}).</pre></div>
    <p>We have to define the record in the shell in order to be able
      use the record syntax in the examples:</p>
    <div class="example"><pre>
&gt; <span class="bold_code">rd(person, {name = "", phone = [], address}).</span>
person</pre></div>
    <p>This is due to the fact that record definitions are available
      at compile time only, not at runtime. See <span class="code">shell(3)</span> for
      details on records in the shell.
      </p>
  

  <h3><a name="id59920">1.3 
        Creating a Record</a></h3>
    
    <p>A new <span class="code">person</span> record is created as follows:</p>
    <div class="example"><pre>
&gt; <span class="bold_code">#person{phone=[0,8,2,3,4,3,1,2], name="Robert"}.</span>
#person{name = "Robert",phone = [0,8,2,3,4,3,1,2],address = undefined}</pre></div>
    <p>Since the <span class="code">address</span> field was omitted, its default value
      is used.</p>
    <p>There is a new feature introduced in Erlang 5.1/OTP R8B,
      with which you can set a value to all fields in a record,
      overriding the defaults in the record specification. The special
      field <span class="code">_</span>, means "all fields not explicitly specified".</p>
    <div class="example"><pre>
&gt; <span class="bold_code">#person{name = "Jakob", _ = '_'}.</span>
#person{name = "Jakob",phone = '_',address = '_'}</pre></div>
    <p>It is primarily intended to be used in <span class="code">ets:match/2</span> and
      <span class="code">mnesia:match_object/3</span>, to set record fields to the atom
      <span class="code">'_'</span>. (This is a wildcard in <span class="code">ets:match/2</span>.)</p>
  

  <h3><a name="id60048">1.4 
        Accessing a Record Field</a></h3>
    
    <div class="example"><pre>
&gt; <span class="bold_code">P = #person{name = "Joe", phone = [0,8,2,3,4,3,1,2]}.</span>
#person{name = "Joe",phone = [0,8,2,3,4,3,1,2],address = undefined}
&gt; <span class="bold_code">P#person.name.</span>
"Joe"</pre></div>
  

  <h3><a name="id61983">1.5 
        Updating a Record</a></h3>
    
    <div class="example"><pre>
&gt; <span class="bold_code">P1 = #person{name="Joe", phone=[1,2,3], address="A street"}.</span>
#person{name = "Joe",phone = [1,2,3],address = "A street"}
&gt; <span class="bold_code">P2 = P1#person{name="Robert"}.</span>
#person{name = "Robert",phone = [1,2,3],address = "A street"}</pre></div>
  

  <h3><a name="id60031">1.6 
        Type Testing</a></h3>
    
    <p>The following example shows that the guard succeeds if
      <span class="code">P</span> is record of type <span class="code">person</span>.</p>
    <div class="example"><pre>
foo(P) when is_record(P, person) -&gt; a_person;
foo(_) -&gt; not_a_person.</pre></div>
  

  <h3><a name="id60080">1.7 
        Pattern Matching</a></h3>
    
    <p>Matching can be used in combination with records as shown in
      the following example:</p>
    <div class="example"><pre>
&gt; <span class="bold_code">P3 = #person{name="Joe", phone=[0,0,7], address="A street"}.</span>
#person{name = "Joe",phone = [0,0,7],address = "A street"}
&gt; <span class="bold_code">#person{name = Name} = P3, Name.</span>
"Joe"</pre></div>
    <p>The following function takes a list of <span class="code">person</span> records
      and searches for the phone number of a person with a particular
      name:</p>
    <div class="example"><pre>
find_phone([#person{name=Name, phone=Phone} | _], Name) -&gt;
    {found,  Phone};
find_phone([_| T], Name) -&gt;
    find_phone(T, Name);
find_phone([], Name) -&gt;
    not_found.</pre></div>
    <p>The fields referred to in the pattern can be given in any order.</p>
  

  <h3><a name="id61405">1.8 
        Nested Records</a></h3>
    
    <p>The value of a field in a record might be an instance of a
      record. Retrieval of nested data can be done stepwise, or in a
      single step, as shown in the following example:</p>
    <div class="example"><pre>
-record(name, {first = "Robert", last = "Ericsson"}).
-record(person, {name = #name{}, phone}).

demo() -&gt;
  P = #person{name= #name{first="Robert",last="Virding"}, phone=123},
  First = (P#person.name)#name.first.</pre></div>
    <p>In this example, <span class="code">demo()</span> evaluates to <span class="code">"Robert"</span>.</p>
  

  <h3><a name="id57989">1.9 
        Example</a></h3>
    
    <div class="example"><pre>
%% File: person.hrl

%%-----------------------------------------------------------
%% Data Type: person
%% where:
%%    name:  A string (default is undefined).
%%    age:   An integer (default is undefined).
%%    phone: A list of integers (default is []).
%%    dict:  A dictionary containing various information 
%%           about the person. 
%%           A {Key, Value} list (default is the empty list).
%%------------------------------------------------------------
-record(person, {name, age, phone = [], dict = []}).</pre></div>
    <div class="example"><pre>
-module(person).
-include("person.hrl").
-compile(export_all). % For test purposes only.

%% This creates an instance of a person.
%%   Note: The phone number is not supplied so the
%%         default value [] will be used.

make_hacker_without_phone(Name, Age) -&gt;
   #person{name = Name, age = Age, 
           dict = [{computer_knowledge, excellent}, 
                   {drinks, coke}]}.

%% This demonstrates matching in arguments

print(#person{name = Name, age = Age,
              phone = Phone, dict = Dict}) -&gt;
  io:format("Name: ~s, Age: ~w, Phone: ~w ~n" 
            "Dictionary: ~w.~n", [Name, Age, Phone, Dict]).

%% Demonstrates type testing, selector, updating.

birthday(P) when record(P, person) -&gt; 
   P#person{age = P#person.age + 1}.

register_two_hackers() -&gt;
   Hacker1 = make_hacker_without_phone("Joe", 29),
   OldHacker = birthday(Hacker1),
   % The central_register_server should have 
   % an interface function for this.
   central_register_server ! {register_person, Hacker1},
   central_register_server ! {register_person, 
             OldHacker#person{name = "Robert", 
                              phone = [0,8,3,2,4,5,3,1]}}.</pre></div>
  
</div>
<div class="footer">
<hr>
<p>Copyright © 2003-2012 Ericsson AB. All Rights Reserved.</p>
</div>
</div>
</div></body>
</html>