next up previous contents
Next: The Types of Structured Up: Structured Types Previous: Nested Types

Selection on Data Structures

In §[*], we discussed some of the advantages structured types offer over lists and sets for storing data. Because instances of a structured type are created by calling a Darwin function which returns an unevaluated function as the structure, we are able to do extensive error checking, simplification and normalization. However, both simple types and the structured type ProEntry defined in §[*] still have the undesirable property that we must remember which index of the structure corresponds to which field of the data type. In our basic example ProEntry, the first index is the name of the entry, the second is database where the entry was found, the third is the accession number into this database, and so forth.

> protent := ProEntry('ABL1_CAEEL', 'SwissProt', 'P03949', 'C. ELEGANS', 
> protent[1];                 # retrieve the name of the sequence
> protent[4];                 # retrieve the organism name
> protent[6];                 # retrieve the length of the sequence
Darwin offers an alternative method called selection for accessing the contents of a structure. Essentially, selection allows us to assign a name to a field of a type in much the same way we assign names to variables and routines. To accomplish this, we create a function named ProEntry_select (in general, the naming convention is the name of the structure type, followed by an underscore symbol (_), followed by the Darwin keyword select). The keyword select is a built-in name with special polymorphic status (for more details on polymorphism see Chapter [*] - Overloading, Polymorphism and Object Orientation).
> ProEntry_select := proc(u, sel, val)
>   upper_sel := uppercase(sel);              
>   if ( upper_sel = 'NAME' ) then
>     if ( nargs = 3 ) then u[1] := val else u[1] fi; 
>   elif ( upper_sel = 'DB' ) then
>     if ( nargs = 3 ) then u[2] := val else u[2] fi;
>   elif ( upper_sel = 'AC' ) then
>     if ( nargs = 3 ) then u[3] := val else u[3] fi;
>   elif ( upper_sel = 'ORGANISM' ) then
>     if ( nargs = 3 ) then u[4] := val else u[4] fi;
>   elif ( upper_sel = 'SEQUENCE' ) then
>     if ( nargs = 3 ) then u[5] := val else u[5] fi;
>   elif ( upper_sel = 'LENGTH' ) then
>     if ( nargs = 3 ) then u[6] := val else u[6] fi;
>   fi;
> end:
Here u is a structure of type ProEntry, sel is the name of the field we wish to access, and val is the value we would like to assign to field u[sel]. A function call such as
> protent['DB'] := 'GenBank';
is equivalent to the call
> ProEntry_select( protent, 'DB', 'GenBank' );
This statement modifies the contents of field 'DB' (the second index) of protent. To examine the contents of a field from protent we omit the third argument val. In this case val is empty and the system name nargs is assigned the value two. ProEntry_select only returns the contents of the field labeled 'DB'.
> protent['Names'];
> protent['DB'];
> protent['DB']:= 'GenBank';
> protent['DB'];

> protent['organism'];
> protent['organism'] := 'H. influenzae';
> protent['organism'];

Be careful! The following two statements are not strictly semantically equivalent.
> protent[6] := 42;
> protent['Length'] := 42;
although they both assign values to the sixth element of the structure protent. The latter statement invokes the ProEntry_select function while the former statement does not. This means that whatever functions ProEntry_select performs above and beyond the assignment of 42 to the field Length (the sixth index) to protent will not be carried out by the assignment protent[6] := 42.

next up previous contents
Next: The Types of Structured Up: Structured Types Previous: Nested Types
Gaston Gonnet