Collections: Difference between revisions

From m204wiki
Jump to navigation Jump to search
mNo edit summary
 
(44 intermediate revisions by 6 users not shown)
Line 5: Line 5:
or a parent might have a number of children.
or a parent might have a number of children.
Traditionally, this type of processing is dealt with using arrays.
Traditionally, this type of processing is dealt with using arrays.
User Language has support for arrays, and the [[Janus SOAP ULI]] extends
Traditional <var class="product">User Language</var> arrays are enhanced by <var class="product">SOUL</var> in Model 204 V7.5 to include support for arrays of structures and objects.
that support by allowing arrays of structures and objects.
   
   
Arrays, however, have some limitations:
Arrays, however, have some limitations:
<ul>
<ul>
<li>They are static. That is, array instances and their size are
<li>They are static. That is, array instances and their size are set at compile-time.
set at compile-time.
<li>There are relatively few things you can do with an array.
<li>There are relatively few things you can do with an array.
Typically, you are limited to setting and retrieving the value of
Typically, you are limited to setting and retrieving the value of
Line 18: Line 16:
Since both of these problems with arrays do not apply to objects,
Since both of these problems with arrays do not apply to objects,
another way to view the problem with arrays is that they are not objects,
another way to view the problem with arrays is that they are not objects,
As a remedy, the [[Janus SOAP ULI]] has a special kind of object that is
As a remedy, <var class="product">SOUL</var> has a special kind of object that is
very much like an array but has all the advantages of an object.
very much like an array but has all the advantages of an object.
These objects are called '''collections'''.
These objects are called '''collections'''.
Line 32: Line 30:
more efficient compiled code.
more efficient compiled code.
   
   
The [[Janus SOAP ULI]] implementation of typed collections provides the best of both
The <var class="product">SOUL</var> implementation of typed collections provides the best of both
worlds: collection objects along with compile-time declaration of the
worlds: collection objects along with compile-time declaration of the
type of the collection elements.
type of the collection elements.
===Collection object declaration syntax===
 
  {variable} [Is] [Collection]                      -
==Collection object declaration syntax==
        collectionType Of [collectionType Of] type  -
<p class="syntax"><span class="squareb">{</span><span class="term">variable</span><span class="squareb">}</span> <span class="squareb">[</span><span class="literal">Is</span><span class="squareb">]</span> <span class="squareb">[</span><span class="literal">Collection</span><span class="squareb">]</span>                     -
              [ Global[(globalName)] ]
    <span class="term">collectionType</span> <span class="literal">Of</span> <span class="squareb">[</span><span class="term">collectionType</span> <span class="literal">Of</span><span class="squareb">]</span> <span class="term">type</span>   -
'''Note:'''
    <span class="squareb">[</span> <span class="literal">Global</span> <span class="squareb">[</span>(<span class="term">globalName</span>)<span class="squareb">]</span> <span class="squareb">]</span>  </p>
The Collection keyword is required before ''Sirius Mods'' version 6.8.
 
<dl>
<table>
<dt>variable
<tr><th>variable</th>
<dd>The name of the object variable that refers to a collection
<td>The name of the object variable that refers to a collection of the indicated type. If outside a class declaration block and structure, the variable must
of the indicated type.
begin with a percent sign. If inside a structure declaration, the variable must not begin with a percent sign. If inside a class declaration block, the variable cannot start with a percent sign and must be preceded by the word <var>Variable</var>.</td></tr>
If outside a class declaration block and structure, the variable must
 
begin with a percent sign.
<tr><th>collectionType</th>
If inside a structure declaration, the variable must not begin with
<td>The name of one of the system collection classes (<var>[[Arraylist class|Arraylist]]</var>, <var>[[NamedArraylist class|NamedArraylist]]</var>, <var>[[FloatNamedArraylist class|FloatNamedArraylist]]</var>, <var>[[UnicodeNamedArraylist class|UnicodeNamedArraylist]]</var>).
a percent sign.
<!-- <var>UnicodeNamedArraylist</var> collections were added in <var class="product">Sirius Mods</var> version 7.6. -->Since collections are always system classes, these names may be preceded with <var>System:</var>.</td></tr>
If inside a class declaration block, the variable cannot start with
 
a percent sign and must be preceded by the word <tt>Variable</tt>.
<tr><th>type</th>
<dt>collectionType
<td>Any basic <var class="product">SOUL</var> datatype, including <var>String</var> (with a length and optional DP), <var>Fixed</var> (with an optional DP), <var>Float</var>, <var>Longstring</var>, <var>Unicode</var>, and <var>Object</var> (followed by the object class).
<dd>The name of one of the system collection classes
<p>
(<tt>Arraylist</tt>, <tt>NamedArraylist</tt>, <tt>FloatNamedArraylist</tt>,
Arrays and structures are not supported as collection items, but collections can themselves be collection items. If <var class="term">type</var> is a collection, you specify both the collection and item datatypes. For example: <code>Arraylist of string len 16</code></p></td></tr>
<tt>UnicodeNamedArraylist</tt>).
 
UnicodeNamedArraylists were added in ''Sirius Mods'' version 7.6.
<tr><th>globalname</th>
Since collections are always system classes, these names may be preceded
<td>The optional global name if the collection variable is not a class or structure variable. If <var>Global</var> is specified without <var class="term">globalName</var>, the name of the variable without a percent sign is used as the global name.</td></tr>
with &ldquo;system:&rdquo;.
</table>
<dt>type
<dd>Any basic User Language datatype, including String (with a length and
optional DP), Fixed (with an optional DP), Float, LongString, Unicode, and
Object (followed by the object class).
Arrays and structures are currently not supported as collection
items, but (as of ''Sirius Mods'' version 7.3)
collections can themselves be collection items.
If ''type'' is a collection, you specify both the collection and
item datatypes.
For example: <tt>Arraylist of string len 16</tt>
<dt>globalname
<dd>The optional global name if the collection variable is
not a class or structure variable.
If <tt>Global</tt> is specified without <tt>globalName</tt>,
the name of the variable without a percent sign is used as the global name.
</dl>
   
   
Collection object declarations do not contain parameters for size
Collection object declarations do not contain parameters for size
Line 80: Line 61:
The number of items in a collection is completely
The number of items in a collection is completely
dynamic, so no arbitrary limit needs to be set on their size (although
dynamic, so no arbitrary limit needs to be set on their size (although
the [[Janus SOAP ULI]] will not support collections with more than 2**31,
<var class="product">SOUL</var> will not support collections with more than 2**31,
or about 2 billion, items).
or about 2 billion, items).
   
   
Collections have one VTBL/STBL slot to hold a single collection
Collections have one VTBL/STBL slot to hold a single collection
element, and all other collection items are kept in CCATEMP.
element, and all other collection items are kept in CCATEMP.
:Note.
 
<p class="note"><b>Note:</b>
For a collection of objects, it is the object references
For a collection of objects, it is the object references
that are kept in CCATEMP, not the actual objects.
that are kept in CCATEMP, not the actual objects.
Line 95: Line 77:
CCATEMP.
CCATEMP.
For this reason, consecutive references to the same collection item
For this reason, consecutive references to the same collection item
are quite efficient.
are quite efficient. </p>
   
   
Here are sample collection object declarations:
Here are sample collection object declarations:
<pre style="xmp">
<p class="code">%scores  is collection arraylist of float
    %scores  is collection Arraylist of float
%costs  is arraylist of fixed dp 2
    %costs  is Arraylist of fixed dp 2
%basket  is floatNamedArraylist of object order
    %basket  is FloatNamedArraylist of object order
%staff  is collection unicodeNamedArraylist of string len 64
    %staff  is collection UnicodeNamedArraylist of string len 64
%value  is namedArraylist of namedArraylist of longstring
    %value  is NamedArraylist of NamedArraylist of longstring
</p>
</pre>
 
==Coding considerations for collections==
==Coding considerations for collections==
Although collections vary by collection type, they are more alike
Although collections vary by collection type, they are more alike than they are different.
than they are different.
The remainder of this article contains topics that address features and methods common to all
This section contains topics that address features and methods common to all
the collection types.
the collection types.
Subsequent sections are devoted to the characteristics and methods
The characteristics and methods of each individual collection type are described in
of each individual collection type:
separate articles; [[#collectionClasses|links]] to those groups of articles are contained
<ul>
in the [[#See also|"See also"]] section below.
<li>[[Arraylist class]]
 
<li>[[NamedArraylist class]]
==Operating on collection items==
<li>[[FloatNamedArraylist class]]
All collections have at least the two standard properties described below.
<li>[[UnicodeNamedArraylist class]]
<table class="thJustBold">
</ul>
<tr><th>Count</th>
===Operating on collection items===
<td>Number of items in collection.</td></tr>
All collections have at least the two standard Property methods
 
described below.
<tr><th>Item</th>
<dl>
<td>A specific item in the collection.
<dt>Count
<dd>Number of items in collection.
<dt>Item
<dd>A specific item in the collection.
   
   
The Item property always takes at least one parameter indicating
The <var>Item</var> property always takes at least one parameter indicating
which item is being referenced, though the type of the parameter
which item is being referenced, though the type of the parameter
can vary with the collection class.
can vary with the collection class.
Line 136: Line 113:
on such a reference.
on such a reference.
   
   
The Item property can be both set and retrieved in all collections.
The <var>Item</var> property can be both set and retrieved in all collections.</td></tr>
</dl>
</table>
   
   
The following example illustrates a simple use of the Count and Item
The following example illustrates a simple use of the <var>Count</var> and <var>Item</var>
methods:
properties:
<pre style="xmp">
<p class="code">%scores  is collection arraylist of float
    %scores  is collection Arraylist of float
...
    ...
%scores = new
    %scores = new
...
    ...
for %i from 1 to %scores:count
    for %i from 1 to %scores:count
  %scores:item(%i) = %scores:item(%i) + 10
      %scores:item(%i) = %scores:item(%i) + 10
end for
    end for
</p>
</pre>
   
   
The Item property name may be left off:
The <var>Item</var> property name may be left off:
<pre style="xmp">
<p class="code">for %i from 1 to %scores:count
    for %i from 1 to %scores:count
  %scores(%i) = %scores(%i) + 10
      %scores(%i) = %scores(%i) + 10
end for
    end for
</p>
</pre>
   
   
If the %scores Arraylist is just one of the members to be updated in the %AllScores
If the <code>%scores</code> <var>Arraylist</var> is just one of the members to be updated in the <code>%allScores</code>
collection of Arraylists, you might have consecutive omissions of the Item name:
collection of <var>Arraylist</var>s, you might have consecutive omissions of the <var>Item</var> name (<code>%allScores(%i)(%j)</code>):
<pre style="xmp">
<p class="code">for %i from 1 to %allScores:count
    for %i from 1 to %AllScores:count
  for %j from 1 to %allScores(%i):count
      for %j from 1 to %AllScores(%i):count
    %allScores(%i)(%j) = %allScores(%i)(%j) + 10
      %AllScores(%i)(%j) = %AllScores(%i)(%j) + 10
  end for
      end for
end for
    end for
</p>
</pre>
   
   
Explicitly specifying the method name, <tt>Item</tt>, is not required because:
Explicitly specifying the method name <var>Item</var>, is not required because:
<ul>
<ul>
<li>It is very convenient to do so, since the Item property is so heavily used.
<li>It is very convenient to omit it, since the <var>Item</var> property is so heavily used.
<li>The Item property always has at least one parameter, so a collection name
 
<li>The <var>Item</var> property always has at least one parameter, so a collection name
followed by a parenthesis can be taken to clearly imply the Item property.
followed by a parenthesis can be taken to clearly imply the Item property.
<li>It facilitates conversion of existing arrays to collections.
<li>It facilitates conversion of existing arrays to collections.
</ul>
</ul>
   
   
Collections also have methods that depend on the collection types.
Collections also have methods that depend on the collection types.
The methods associated with the [[Janus SOAP ULI]] collection types
The methods associated with the <var class="product">SOUL</var> collection types
(Arraylists, NamedArraylists, FloatNamedArraylists, UnicodeNamedArraylists)
(<var>Arraylist</var>, <var>NamedArraylist</var>, <var>FloatNamedArraylist</var>, <var>UnicodeNamedArraylist</var>)
are described in subsequent sections.
are described in subsequent sections.
   
   
In the descriptions of the methods, the term '''item''' means
In the descriptions of the methods, the term '''item''' means
a value or variable of the same <tt>type</tt> as specified on the collection
a value or variable of the same ''type'' as specified on the collection
declaration, or a value or variable convertible to that type.
declaration, or a value or variable convertible to that type.
For example, if a collection is declared as:
For example, if a collection is declared as:
<pre style="xmp">
<p class="code">%stooges is arraylist of object stooge
    %stooges is Arraylist of object stooge
</p>
</pre>
An <var>Add</var> method applied to <code>%stooges</code> can only add an object of class <code>stooge</code>:
<p class="code">%moe  is object stooge
and the Add method for Arraylist is declared as <tt>%var:add(item)</tt>,
...
an Add method applied to %stooges can only add an object of class stooge:
%stooges:add(%moe)
<pre style="xmp">
</p>
    %moe  is object stooge
    ...
    %stooges:add(%moe)
</pre>
   
   
On the other hand, if a collection is declared as
On the other hand, if a collection is declared as
<pre style="xmp">
<p class="code">%value is Arraylist of string len 16
    %value is Arraylist of string len 16
</p>
</pre>
you can add anything that can be converted to a string:
you can add anything that can be converted to a string:
<pre style="xmp">
<p class="code">%long is longstring
    %long is longstring
  ...
      ...
%value:add('A string')
    %value:add('A string')
%value:add(22)
    %value:add(22)
%value:add(%long)
    %value:add(%long)
</p>
</pre>
 
'''Note:'''
<p class="note"><b>Note:</b>
In the example above, as is usual with longstrings, a truncation
In the example above, as is usual with longstrings, a truncation
of the longstring on addition would cause a request cancellation error.
of the longstring on addition would cause a request cancellation error.
===Comparing and assigning new collection variables===
</p>
 
==Comparing and assigning new collection variables==
Collection variables, being a special variety of object variables,
Collection variables, being a special variety of object variables,
can be assigned to each other and compared, just like other object
can be assigned to each other and compared, just like other object
variables:
variables:
<pre style="xmp">
<p class="code">%alist  is arraylist of longstring
    %alist  is Arraylist of longstring
%blist  is arraylist of longstring
    %blist  is Arraylist of longstring
...
    ...
%blist = %alist
    %blist = %alist
...
    ...
if %alist eq %blist then
    if %alist eq %blist then
</p>
</pre>
 
For assignment or comparison to be allowed, however, both the
For assignment or comparison to be allowed, however, both the
collection type (Arraylist, for example) and the collection
collection type (<var>Arraylist</var>, for example) and the collection
item datatype must be identical.
item datatype must be identical.
As just two examples, you cannot assign the contents of an Arraylist
As just two examples, you cannot assign the contents of an <var>Arraylist</var>
variable to a NamedArraylist variable, and you cannot assign the contents
variable to a <var>NamedArraylist</var> variable, and you cannot assign the contents
of an Arraylist Of Longstring to an Arraylist Of Float.
of an <code>arraylist of longstring</code> to an <code>arraylist of float</code>.
'''Note:'''
 
When assigning to a collection variable and
<blockquote class="note"><b>Note:</b>
using the syntax of the New function that explicitly indicates the
When assigning to a collection variable and using the syntax of the <var>New</var> function that explicitly indicates the
class for collections, both the collection and item datatypes must be
class for collections, both the collection and item datatypes must be
specified just as on the collection variable declaration:
specified just as on the collection variable declaration:
<pre style="xmp">
<p class="code">%alist  is collection floatNamedArraylist of longstring
    %alist  is collection FloatNamedArraylist of longstring
%alist  = %(floatNamedArraylist of longstring):new
    %alist  = %(FloatNamedArraylist of longstring):new
</p> </blockquote>
</pre>
 
===Printing a collection===
==Printing a collection==
In versions of the ''Sirius Mods'' prior to 7.6, the
<!-- In versions of the <var class="product">Sirius Mods</var> prior to 7.6 -->Formerly, the
standard way to view the entire contents of a collection is
standard way to view the entire contents of a collection was
to loop through the list items and display each one using a User Language Print
to loop through the list items and display each one using a <var class="product">SOUL</var> <var>Print</var> statement
statement
(or <var>Audit</var> or <var>Trace</var>).
(or Audit or Trace).
For a <var>NamedArraylist</var>, for example, you used a method for the item subscript name and a method for the item content:
For a NamedArraylist, for example, you use a method for
<p class="code">%nal  is namedArraylist of float
the item subscript name and a method for the item content:
...
<pre style="xmp">
    %nal  is namedArraylist of float
    ...
   
   
    %nal = new
%nal = new
    %nal('Chicago') = 22
%nal('Chicago') = 22
    %nal('New York') = -999
%nal('New York') = -999
    %nal('Los Angeles') = 3.1415926
%nal('Los Angeles') = 3.1415926
    %nal('Philadelphia') = 1099
%nal('Philadelphia') = 1099
   
   
    for %i from 1 to %nal:count
for %i from 1 to %nal:count
      print %nal:nameByNumber(%i) and %nal:itemByNumber(%i)
  print %nal:nameByNumber(%i) and %nal:itemByNumber(%i)
    end for
end for
</pre>
</p>
   
   
This is the result:
This is the result:
<pre style="xmp">
<p class="output">Chicago 22
    Chicago 22
Los Angeles 3.1415926
    Los Angeles 3.1415926
New York -999
    New York -999
Philadelphia 1099
    Philadelphia 1099
</p>
</pre>
   
   
As of version 7.6 of the ''Sirius Mods'', the Print method for any collection
<!-- As of version 7.6 of the <var class="product">Sirius Mods</var> -->Now, the <var>Print</var> method for any collection
does the work of the loop in the preceding example, and more.
does the work of the loop in the preceding example, and more.
Supplied for debugging purposes, Print (or the essentially
Supplied for debugging purposes, <var>Print</var> (or the essentially
identical Audit or Trace method) would produce the following output
identical <var>Audit</var> or <var>Trace</var> method) would produce the following output
using the example collection above (that is: <tt>%nal:print</tt>):
using the example collection above (that is: <code>%nal:print</code>):
<pre style="xmp">
<p class="code">1: Chicago: 22
    1: Chicago: 22
2: Los Angeles: 3.1415926
    2: Los Angeles: 3.1415926
3: New York: -999
    3: New York: -999
4: Philadelphia: 1099
    4: Philadelphia: 1099
</p>
</pre>
   
   
Notice that Print outputs all the collection items (or, optionally, a
Notice that <var>Print</var> outputs all the collection items (or, optionally, a
range of items), and it also includes:
range of items), and it also includes:
<ul>
<ul>
Line 291: Line 258:
</ul>
</ul>
   
   
Print also has optional parameters that let you specify:
<var>Print</var> also has optional parameters that let you specify:
<ul>
<ul>
<li>The lengths for the item name and number
<li>The lengths for the item name and number
Line 297: Line 264:
<li>The number of items to display
<li>The number of items to display
</ul>
</ul>
'''Note:'''
 
The Print method applies a ToString method (by default) to each item value
<blockquote class="note"><b>Note:</b>
The <var>Print</var> method applies a <var>ToString</var> method (by default) to each item value
(and always to each item name), to produce its result.
(and always to each item name), to produce its result.
Applying Print to a collection whose item types are ''not'' system classes
Applying <var>Print</var> to a collection whose item types are ''not'' system classes
will work only if:
will work only if at least one of the following is true:
<ul>
<ul>
<li>The user class contains a ToString method.
<li>The user class contains a <var>ToString</var> method.
<li>The Print method includes an appropriate &ldquo;method parameter,&rdquo;
<li>The <var>Print</var> method includes an appropriate "method parameter,"
as described below.
as described below.
</ul>
</ul></blockquote>
   
   
====General syntax of Print (Audit or Trace) for a collection====
===General syntax of Print (Audit or Trace) for a collection===
  %coll:Print (<method>, <numWidth>, <nameWidth>,      -
<p class="syntax"><span class="term">%coll</span>:<span class="literal">Print</span> (<span class="term">method</span>, <span class="term">numWidth</span>, <span class="term">nameWidth</span>,      -
                <separator>, <start>, <maxItems>, <label>)
            <span class="term">separator</span>, <span class="term">start</span>, <span class="term">maxItems</span>, <span class="term">label</span>)  
</p>
   
   
All parameters are optional and all except <method> have required names
All parameters are optional and all except <var class="term">method</var> have required names (which match the names used in the syntax above).
(which match the names used in the syntax above).
The parameters are described briefly below and in greater detail in the
The parameters are described briefly below and in greater detail in the
method descriptions for the appropriate collection type later in this chapter.
[[List of Collection methods|individual method descriptions]] for the appropriate collection type.
<dl>
<table class="syntaxTable">
<dt><method>
<tr><th>method</th>
<dd>The method applied to collection items to produce the printed output.
<td>The method applied to collection items to produce the printed output.
The method must take no parameters and produce an intrinsic (Float,
The method must take no parameters and produce an intrinsic (<var>Float</var>,
String, Fixed, Unicode) value.
<var>String</var>, <var>Fixed</var>, <var>Unicode</var>) value.
It may be a system or user-written method, a class Variable or Property, a
It may be a system or user-written method, a class variable or property, a
local method, or a method variable.
local method, or a method variable. The default is the <var>ToString</var> method. </td></tr>
The default is the ToString method.
 
<dt><numWidth>
<tr><th>numWidth</th>
<dd>The number of bytes for the item number in the output.
<td>The number of bytes for the item number in the output. If 0, the default, the item number is not printed.</td></tr>
If 0, the default, the item number is not printed.
 
<dt><namewidth>
<tr><th>nameWidth</th>
<dd>The number of bytes for the item name (ignored if an Arraylist).
<td>The number of bytes for the item name (ignored if an Arraylist).
If -1, the default, the entire name is fit exactly.
If -1, the default, the entire name is fit exactly. If 0, the item name is not printed.</td></tr>
If 0, the item name is not printed.
 
<dt><separator>
<tr><th>separator</th>
<dd>A string that follows the item number and that repeats after
<td>A string that follows the item number and that repeats after the item name. The default is a colon.
the item name.
A blank follows each instance of ''separator''.</td></tr>
The default is a colon.
 
A blank follows each instance of ''separator''.
<tr><th>start</th>
<dt><start>
<td>The number of the collection item from which to start the output display.
<dd>The number of the collection item from which to start the output display.
By default, the display begins from item one.</td></tr>
By default, the display begins from item one.
 
<dt><maxItems>
<tr><th>maxItems</th>
<dd>The maximum number of collection items to print.
<td>The maximum number of collection items to print. By default, all items are displayed.</td></tr>
By default, all items are displayed.
 
<dt><label>
<tr><th>label</th>
<dd>A string, null by default, marking the beginning of each item's line of output.
<td>A string, null by default, marking the beginning of each item's line of output.</td></tr>
</dl>
</table>
   
   
====Examples providing xWidth or local method arguments====
===Examples using width or local method arguments===
For the NamedArraylist in the first example in "[[#Printing a collection|Printing a
For the <var>NamedArraylist</var> in the first example in "[[#Printing a collection|Printing a
collection]]",
collection]]", but issuing <code>%nal:print(numWidth=3, nameWidth=14)</code>,
but issuing <tt>%nal:print(numWidth=3, nameWidth=14)</tt>,
this is the result:
this is the result:
<pre style="xmp">
<p class="output">1: Chicago      : 22
      1: Chicago      : 22
2: Los Angeles  : 3.1415926
      2: Los Angeles  : 3.1415926
3: New York      : -999
      3: New York      : -999
4: Philadelphia  : 1099
      4: Philadelphia  : 1099
</p>
</pre>
   
   
If you issue <tt>%nal:print(numWidth=3, nameWidth=7)</tt>,
If you issue <code>%nal:print(numWidth=3, nameWidth=7)</code>,
the result is:
the result is:
<pre style="xmp">
<p class="output">1: Chicago: 22
      1: Chicago: 22
2: Los Ang: 3.1415926
      2: Los Ang: 3.1415926
3: New Yor: -999
      3: New Yor: -999
4: Philade: 1099
      4: Philade: 1099
</p>
</pre>
   
   
You can define a local function to display your output:
You can define a local function to display your output:
<pre style="xmp">
<p class="code">local function (string):quote is longstring
    local function (string):quote is longstring
  return &apos;&apos;&apos;&apos; with %this with &apos;&apos;&apos;&apos;
      return '''' with %this with ''''
end function
    end function
</p>
</pre>
   
   
Now you issue:
Now you issue:
<pre style="xmp">
<p class="code">%nal:print(quote)
    %nal:print(quote)
</p>
</pre>
   
   
And you get this result:
And you get this result:
<pre style="xmp">
<p class="output">1: Chicago: '22'
    1: Chicago: '22'
2: Los Angeles: '3.1415926'
    2: Los Angeles: '3.1415926'
3: New York: '-999'
    3: New York: '-999'
4: Philadelphia: '1099'
    4: Philadelphia: '1099'
</p>
</pre>
   
   
If you named your local method <tt>ToString</tt> instead of <tt>Quote</tt>,
If you named your local method <code>toString</code> instead of <code>quote</code>,
it would not need to be specified on the Print method.
it would not need to be specified on the <var>Print</var> method.
This is shown in the following example.
This is shown in the following example.
 
====Examples using class or local ToString====
===Examples using class or local ToString===
In the following request, the method parameter used with the Arraylist Print
In the following request, the method parameter used with the <var>Arraylist</var> <var>Print</var>
method is a class Variable:
method is a class variable:
<pre style="xmp">
<p class="code">b
b
class python
class python
   public
   public
Line 425: Line 386:
%pythons:print(surname)
%pythons:print(surname)
end
end
</pre>
</p>
   
   
The request result is:
The request result is:
<pre style="xmp">
<p class="output">1: Cleese
    1: Cleese
2: Palin
    2: Palin
3: Idle
    3: Idle
4: Chapman
    4: Chapman
5: Jones
    5: Jones
</p>
</pre>
   
   
If you create the following ToString method in the class:
If you create the following <code>ToString</code> method in the class:
<pre style="xmp">
<p class="code">function toString is longstring
    function toString is longstring
  return 'surname=' with %this:surname with ', ' with -
      return 'surname=' with %this:surname with ', ' with -
        'givenName=' with %this:givenName with ', ' with -
            'givenName=' with %this:givenName with ', ' with -
        'routine=' with %this:routine
            'routine=' with %this:routine
end function
    end function
</p>
</pre>
   
   
And you issue this Print method call, which implicitly invokes
And you issue this <var>Print</var> method call, which implicitly invokes
your ToString method:
your <code>toString</code> method:
<pre style="xmp">
<p class="code">%pythons:print(start=2, maxItems=3)
    %pythons:print(start=2, maxItems=3)
</p>
</pre>
   
   
The result is:
The result is:
<pre style="xmp">
<p class="output">2: surname=Palin, givenName=Michael, routine=Lumberjack
    2: surname=Palin, givenName=Michael, routine=Lumberjack
3: surname=Idle, givenName=Eric, routine=Nudge nudge
    3: surname=Idle, givenName=Eric, routine=Nudge nudge
4: surname=Chapman, givenName=Graham, routine=Throat
    4: surname=Chapman, givenName=Graham, routine=Throat
  Wobbler Mangrove
      Wobbler Mangrove
</p>
</pre>
 
====Examples of "subscript" display format for named collections====
===Examples of subscript display format for named collections===
When printing the name subscript for NamedArraylists, the subscript is left as is.
When printing the name subscript for a <var>NamedArraylist</var>, the subscript is left as is.
For FloatNamedArraylists, the float subscripts are displayed as strings.
For a <var>FloatNamedArraylist</var>, the <var>Float</var> subscripts are displayed as strings.
For UnicodeNamedAraylists, the float Unicode are translated from Unicode to EBCDIC,
For a <var>UnicodeNamedAraylist</var>, the <var>Unicode</var> subscripts are translated from <var>Unicode</var> to EBCDIC,
(character-entity-encoding any non-translatable characters), as in
(character-entity-encoding any non-translatable characters), as in the following:
the following:
<p class="code">%transcendental    is unicodeNamedArraylist of float
<pre style="xmp">
...
    %transcendental    is unicodeNamedArraylist of float
%transcendental = new
    ...
%transcendental('&amp;pi;':[[U (String function)|U]]) = 3.1415926
    %transcendental = new
%transcendental:print
    %transcendental('&amp;pi;':U) = 3.1415926
</p>
    %transcendental:print
</pre>
The <var>Print</var> result shows the encoded form of the Unicode item name:
<p class="output">1: &amp;#x03C0;: 3.1415926
</p>
 
<blockquote class="note">
<p><b>Note:</b>
If you specified <code>%transcendental:print(namewidth=4)</code>, for example,
the item name '''is''' truncated:</p>
<p class="output">1: &amp;#x: 3.1415926 </p>
</blockquote>
   
   
The <tt>U</tt> method used above is described in "[[U (String function)|U]]".
==Finding collection maxima and minima, and sorting==
The Print result shows the encoded form of the Unicode item name:
In addition to <var>Count</var> and <var>Item</var> methods, all collections also have <var>Maximum</var>
<pre style="xmp">
and <var>Minimum</var> methods.<!-- (as of <var class="product">Sirius Mods</var> 7.3) -->
    1: &amp;#x03C0;: 3.1415926
</pre>
'''Note:'''
If you specified <tt>%transcendental:print(namewidth=4)</tt>, for example,
the item name '''is''' truncated:
<pre style="xmp">
    1: &amp;#x: 3.1415926
</pre>
===Finding collection maxima and minima, and sorting===
In addition to Count and Item methods, all collections also have Maximum
and Minimum methods (as of ''Sirius Mods'' 7.3).
These are methods that let you find the collection item that returns the highest
These are methods that let you find the collection item that returns the highest
or lowest value, respectively, for the attribute you want to evaluate.
or lowest value, respectively, for the attribute you want to evaluate.
Line 492: Line 448:
string or numeric value.
string or numeric value.
   
   
Arraylists and NamedArraylists also have sorting methods that are similar to
<var>Arraylist</var> and <var>NamedArraylist</var> collections
Maximum and Minimum but which sort a collection by the attribute function
also have sorting methods that are similar to
<var>Maximum</var> and <var>Minimum</var> but which sort a collection by the attribute function
you specify.
you specify.
   
   
Line 505: Line 462:
The following series of examples introduces the maximum/minimum and sorting
The following series of examples introduces the maximum/minimum and sorting
methods and displays many of the types of function parameter you can implement.
methods and displays many of the types of function parameter you can implement.
====Finding a maximum using a system method parameter====
 
In the following request, the Maximum method first
===Finding a maximum using a system method parameter===
applies the Stinglist [[Count (Arraylist property)|Count]] function to each item
In the following request, the <var>Maximum</var> method first
in an Arraylist of Stringlist items.
applies the <var>Stringlist</var> <var>[[Count (Arraylist property)|Count]]</var> function to each item
The Count function is specified as a parameter to the Maximum method.
in an <var>Arraylist</var> of <var>Stringlist</var> items.
Maximum then returns the position in the Arraylist of the Stringlist
The <var>Count</var> function is specified as a parameter to the <var>Maximum</var> method.
<var>Maximum</var> then returns the position in the <var>Arraylist</var> of the <var>Stringlist</var>
that has the most items.
that has the most items.
The [[List (Stringlist function)|List]] function simplifies the construction of the lists.
The <var>[[List (Stringlist function)|List]]</var> function simplifies the construction of the lists.
<pre style="xmp">
<p class="code">b
    b
%I is float
    %I is float
%list1 is object stringlist
    %list1 is object stringlist
%list2 is object stringlist
    %list2 is object stringlist
%list3 is object stringlist
    %list3 is object stringlist
   
   
    %list1 = List('the', 'quick', 'brown')
%list1 = List('the', 'quick', 'brown')
    %list2 = List('fox', 'jumped', 'over', 'the')
%list2 = List('fox', 'jumped', 'over', 'the')
    %list3 = List('lazy', 'dog', 'yesterday', 'two', 'times')
%list3 = List('lazy', 'dog', 'yesterday', 'two', 'times')
   
   
    %arrayl is collection arraylist of object stringlist
%arrayl is collection arraylist of object stringlist
    %arrayl = List(%list1, %list2, %list3)
%arrayl = List(%list1, %list2, %list3)
   
   
    Print 'The longest list is item ' %arrayl:maximum(count)
print 'The longest list is item ' %arrayl:maximum(count)
    end
end
</pre>
</p>
   
   
The result is:
The result is:
<pre style="xmp">
<p class="output">The longest list is item 3
    The longest list is item 3
</p>
</pre>
 
====Finding a minimum using a class Variable parameter====
===Finding a minimum using a class Variable parameter===
The function you apply to the collection items is not restricted to system
The function you apply to the collection items is not restricted to system
class methods.
class methods.
More precisely, the function parameter is a method value: it can be the
More precisely, the function parameter is a method value: it can be the
name of a system method, as above, or a user method or local method
name of a system method, as above, or a user method or [[Local methods|local method]].
([[??]] refid=localm.).
Or the function parameter can be a [[Method variables|Function variable]],
Or the function parameter can be a Function variable ([[Method variables]]),
including a class <var>Variable</var> or <var>Property</var>.
including a class Variable or Property.
Any of these types of method value are valid as long as they a) operate on the item type in the collection, and b) return
Any of these types of method value are valid as long as they
an [[Intrinsic classes#Intrinsic methods in User Language|intrinsic]] (number, string, unicode) value.
1) operate on the item type in the collection, and 2) return
an
[[Intrinsic classes#Intrinsic methods in User Language|intrinsic]]
(number, string, unicode) value.
   
   
In the following example, the Minimum method applies a class Variable
In the following example, the <var>Minimum</var> method applies a class variable
to determine the Arraylist item with the minimum value.
to determine the <var>Arraylist</var> item with the minimum value.
The [[List (Arraylist function)|List]] function simplifies the construction of
The <var>[[List (Arraylist function)|List]]</var> function simplifies the construction of
the Arraylist.
the <var>Arraylist</var>.
<pre style="xmp">
<p class="code">b
    b
   
   
    class python
class python
    public
public
      variable firstname is string len 16
  variable firstname is string len 16
      variable surname is string len 16
  variable surname is string len 16
      variable birthdate is float
  variable birthdate is float
      constructor newpy (%sname is string len 16, -
  constructor newpy (%sname is string len 16, -
        %name is string len 16, %bd is float)
    %name is string len 16, %bd is float)
    end public
end public
   
   
    constructor newpy (%sname is string len 16,  -
constructor newpy (%sname is string len 16,  -
      %name is string len 16, %bd is float)
  %name is string len 16, %bd is float)
      %this:firstname = %name
  %this:firstname = %name
      %this:surname = %sname
  %this:surname = %sname
      %this:birthdate = %bd
  %this:birthdate = %bd
    end constructor
end constructor
    end class
end class
   
   
    %lp is arraylist of object python
%lp is arraylist of object python
   
   
    %lp = list(newpy('Gilliam', 'Terry', '19401122'),  -
%lp = list(newpy('Gilliam', 'Terry', '19401122'),  -
              newpy('Cleese', 'John', '19391027'),    -
            newpy('Cleese', 'John', '19391027'),    -
              newpy('Idle', 'Eric', '19430329'),      -
            newpy('Idle', 'Eric', '19430329'),      -
              newpy('Palin', 'Michael', '19430505'),  -
            newpy('Palin', 'Michael', '19430505'),  -
              newpy('Chapman', 'Graham', '19410108'),  -
            newpy('Chapman', 'Graham', '19410108'),  -
              newpy('Jones', 'Terry', '19420201') )
            newpy('Jones', 'Terry', '19420201') )
   
   
    print 'Item ' %lp:minimum(birthdate) ' has eldest Python'
print 'Item ' %lp:minimum(birthdate) ' has eldest Python'
   
   
    end
end
</pre>
</p>
   
   
The result is:
The result is:
<pre style="xmp">
<p class="output">Item 2 has eldest Python
    Item 2 has eldest Python
</p>
</pre>
 
====Sorting an Arraylist using one sort criterion====
===Sorting an Arraylist using one sort criterion===
The Arraylist of Python above can be readily sorted by birthdate as well.
The <var>Arraylist</var> of <code>python</code> objects above can be readily sorted by <code>birthdate</code> as well.
The Sort and SortNew methods of the Arraylist class take as input
The <var>Arraylist</var> <var>Sort</var> and <var>SortNew</var> methods take as input
the sorting criteria, a combination of a
the sorting criteria, a combination of a
sorting order direction (Ascending or Descending) and its sort key parameter
sorting order direction (<var>Ascending</var> or <var>Descending</var>) and its sort key parameter
(a function just like that in Maximum/Minimum which operates on the collection items).
(a function just like that in <var>Maximum</var>/<var>Minimum</var> which operates on the collection items).
This direction and sort key combination is also known as a
This direction and sort key combination is also known as a <var>[[SortOrder class|SortOrder]]</var>.
[[SortOrder class|SortOrder]].
   
   
For example, to sort the Python Arraylist in ascending order by birthdate,
For example, to sort the <var>Arraylist</var> of <code>python</code> objects
you can use the Sort subroutine:
in ascending order by <code>birthdate</code>, you can use the <var>Sort</var> subroutine:
<pre style="xmp">
<p class="code">call %lp:sort(ascending(birthdate))
    Call %lp:sort(ascending(birthdate))
</p>
</pre>
   
   
Or you can use the SortNew function:
Or you can use the <var>SortNew</var> function:
<pre style="xmp">
<p class="code">%lp = %lp:sortnew(ascending(birthdate))
    %lp = %lp:sortnew(ascending(birthdate))
</p>
</pre>
   
   
If you provide the Python class with a method to print a Python object,
If you provide the <code>python</code> class with a method to print a <code>python</code> object,
then loop through the sorted Arraylist returned by SortNew:
then loop through the sorted <var>Arraylist</var> returned by <var>SortNew</var>:
<pre style="xmp">
<p class="code">class python
    class python
...
    ...
function myprint is longstring
    function myprint is longstring
  return %this:firstname with ' ' with -
      return %this:firstname with ' ' with -
          %this:surname with '  ' with -
              %this:surname with '  ' with -
          '(born: ' with %this:birthdate with ')'
              '(born: ' with %this:birthdate with ')'
end function
    end function
end class
    end class
...
    ...
%i is float
    %i is float
%lp = %lp:sortnew(ascending(birthdate))
    %lp = %lp:sortnew(ascending(birthdate))
for %i from 1 to %lp:count
    for %i from 1 to %lp:count
  print %lp(%i):myprint
      print %lp(%i):myprint
end for
    end for
</p>
</pre>
   
   
This is the sorted result:
This is the sorted result:
<pre style="xmp">
<p class="output">John Cleese  (born: 19391027)
    John Cleese  (born: 19391027)
Terry Gilliam  (born: 19401122)
    Terry Gilliam  (born: 19401122)
Graham Chapman  (born: 19410108)
    Graham Chapman  (born: 19410108)
Terry Jones  (born: 19420201)
    Terry Jones  (born: 19420201)
Eric Idle  (born: 19430329)
    Eric Idle  (born: 19430329)
Michael Palin  (born: 19430505)
    Michael Palin  (born: 19430505)
</p>
</pre>
====Finding minima using a method variable parameter====
<p class="note"><b>Note:</b>
The function-like method value parameter in Maximum, Minimum, and sorting
Of the collection classes, only the <var>Arraylist</var> class contains a <var>Sort</var> subroutine; all the collection classes have a <var>SortNew</var> function. </p>
===Finding minima using a method variable parameter===
The function-like method value parameter in <var>Maximum</var>, <var>Minimum</var>, and sorting
may be a [[Method variables|method variable]].
may be a [[Method variables|method variable]].
<tt>%meth</tt> in the following simple example is assigned in turn to
<code>%meth</code> in the following simple example is assigned in turn to
two [[Local and Common entities#Defining and invoking a local
two [[Local methods|local]] functions:
method|local]] functions:
<p class="code">b
<pre style="xmp">
%meth  is function (string):func is longstring
    b
    %meth  is function (string):func is longstring
   
   
    Local function (string):leftmost is longstring
Local function (string):leftmost is longstring
      return %this:left(1)
  return %this:left(1)
    end function
end function
   
   
    Local function (string):rightmost is longstring
Local function (string):rightmost is longstring
      return %this:right(1)
  return %this:right(1)
    end function
end function
   
   
    %l  is arraylist of string len 30
%l  is arraylist of string len 30
   
   
    %l = list('Hickory, 'Dickory', 'Doc')
%l = list('Hickory', 'Dickory', 'Doc')
    %meth = rightmost
%meth = rightmost
    print %l:minimum(%meth)
print %l:minimum(%meth)
   
   
    %meth = leftmost
%meth = leftmost
    print %l:minimum(%meth)
print %l:minimum(%meth)
    end
end
</pre>
</p>
   
   
This request prints the number of the item that
This request prints the number of the item that has the rightmost character that is alphabetically the earliest, then the number of the item that has the leftmost character that is
has the rightmost character that is alphabetically the
earliest, then the number of the item that has the leftmost character that is
the earliest (and closer to the beginning of the list):
the earliest (and closer to the beginning of the list):
<pre style="xmp">
<p class="output">3
    3
2
    2
</p>
</pre>
 
'''Note:'''
<blockquote class="note">
Specifying the local functions themselves as the Minimum
<p><b>Note:</b>
Specifying the local functions themselves as the <var>Minimum</var>
method parameter in the preceding example would also produce the same result.
method parameter in the preceding example would also produce the same result.
For example, the first <tt>print %l:minimum(%meth)</tt> call in the example
For example, the first <code>print %l:minimum(%meth)</code> call in the example
is equivalent to <tt>print %l:minimum(rightmost)</tt>.
is equivalent to <code>print %l:minimum(rightmost)</code>. </p>
<p>
However, explicitly specifying <tt>right(1)</tt>
However, explicitly specifying <code>right(1)</code>
(the method and argument that local function <tt>rightmost</tt> invokes)
(the method and argument that local function <code>rightmost</code> invokes)
as the Minimum parameter does '''not''' work.
as the Minimum parameter does '''not''' work.
Specifying a method that itself requires a parameter as the Minimum (or Maximum
Specifying a method that itself requires a parameter as the <var>Minimum</var> (or <var>Maximum</var>
or sort) parameter is a syntax violation and compilation error.
or sort) parameter is a syntax violation and compilation error.
The parameter for Minimum is a method value, not a User Language expression.
The parameter for <var>Minimum</var> is a method value, not a <var class="product">SOUL</var> expression.
You can use a local function as the Minimum parameter, as in the example above,
You can use a local function as the <var>Minimum</var> parameter, as in the example above,
to apply a method that requires an argument.
to apply a method that requires an argument. </p>
====Using the This function as the Maximum parameter====
</blockquote>
Finding the Maximum, Minimum, and sorting are likely
 
to be very common operations on collections of User Language intrinsic values.
===Using the This function as the Maximum parameter===
Finding the <var>Maximum</var>, <var>Minimum</var>, and sorting are likely
to be very common operations on collections of <var class="product">SOUL</var> intrinsic values.
In these cases, you want the function parameter for the maximum/minimum
In these cases, you want the function parameter for the maximum/minimum
and sorting methods to be an identity function like in the following:
and sorting methods to be an identity function like in the following:
<pre style="xmp">
<p class="code">b
    b
%l  is arraylist of float
    %l  is arraylist of float
%l = list(9, 11, 4, -5, 17, 3, 4, 6)
    %l = list(9, 11, 4, -5, 17, 3, 4, 6)
   
   
    local function (string):thisVal is float
local function (float):thisVal is float
      return %this
  return %this
    end function
end function
   
   
    Print 'item ' %l:maximum(thisVal) ' has the maximum value'
printText Item {%l:maximum(thisVal)} has the maximum value
    end
end
</pre>
</p>
To simplify such requests, a special method value <!-- introduced in <var class="product">Sirius Mods</var> 7.3 -->
provides the identity function for intrinsic classes.
The method value (named <var>This</var>) simply returns the value of the method object.
''It is valid only for intrinsic classes.''
   
   
To simplify such requests, a special method value introduced in ''Sirius Mods'' 7.3
Using <var>This</var>, the previous request becomes:
provides the identity function for intrinsic items.
<p class="code">b
The method (named <tt>This</tt>) simply returns the value of the method object.
%l  is arraylist of float
''It is valid only when applied to User Language intrinsic method objects.''
%l = list(9, 11, 4, -5, 17, 3, 4, 6)
printText Item {%l:maximum(this)} has the maximum value
Using <tt>This</tt>, the previous request becomes:
end
<pre style="xmp">
</p>
    b
Since <var>This</var> is the default method value <!-- (as of <var class="product">Sirius Mods</var> version 7.6) -->
    %l  is arraylist of float
    %l = list(9, 11, 4, -5, 17, 3, 4, 6)
    Print 'item ' %l:maximum(this) ' has the maximum value'
    end
</pre>
Since <tt>This</tt> is the default method value (as of ''Sirius Mods'' version 7.6)
for the maximum/minimum/sorting
for the maximum/minimum/sorting
function parameter, <tt>%l:maximum(this)</tt> above can be replaced by:
function parameter, <code>%l:maximum(this)</code> above can be replaced by:
<pre style="xmp">
<p class="code">%l:maximum
    %l:maximum
</p>
</pre>
And <code>sort(descending(this))</code>, for example, can be replaced by:
<p class="code">%l:sort(descending)
</p>
   
   
And <tt>sort(descending(this))</tt>, for example, can be replaced by:
===Sorting an Arraylist using two sort criteria===
<pre style="xmp">
    %l:sort(descending)
</pre>
====Sorting an Arraylist using two sort criteria====
The following request sorts an Arraylist by two sort criteria.
The following request sorts an Arraylist by two sort criteria.
A [[SortOrder class|SortOrder]] object
A <var>[[SortOrder class|SortOrder]]</var> object
is explicitly defined to contain the sort criteria.
is explicitly defined to contain the sort criteria.
The [[List (Arraylist function)|List]] function simplifies the construction of
The <var>[[List (Arraylist function)|List]]</var> function simplifies the construction of
the
the <var>Arraylist</var>.
Arraylist.
<p class="code">b
<pre style="xmp">
    b
   
   
    class polis
class polis
    public
public
      variable city is string len 16
  variable city is string len 16
      variable dept is string len 10
  variable dept is string len 10
      variable cost is float
  variable cost is float
      constructor newp (%city is string len 16, -
  constructor newp (%city is string len 16, -
      %dp is string len 10, %cst is float)
    %dp is string len 10, %cst is float)
      function myprint is longstring
  function myprint is longstring
    end public
end public
   
   
    constructor newp (%city is string len 16, -
constructor newp (%city is string len 16, -
      %dp is string len 10, %cst is float)
  %dp is string len 10, %cst is float)
      %this:city = %city
  %this:city = %city
      %this:dept = %dp
  %this:dept = %dp
      %this:cost = %cst
  %this:cost = %cst
    end constructor
end constructor
   
   
    function myprint is longstring
function myprint is longstring
      return %this:city with ' (' with -
  return %this:city with ' (' with -
              %this:dept with '): ' with %this:cost
          %this:dept with '): ' with %this:cost
    end function
end function
    end class
end class
   
   
    %lp is arraylist of object polis
%lp is arraylist of object polis
    %lp = list(newp('Gotham', 'DPW', 33125), -
%lp = list(newp('Gotham', 'DPW', 33125), -
              newp('Chatham', 'Fire', 21940), -
          newp('Chatham', 'Fire', 21940), -
              newp('Wareham', 'Fire', 8444),    -
          newp('Wareham', 'Fire', 8444),    -
              newp('Wareham', 'DPW', 5938),      -
          newp('Wareham', 'DPW', 5938),      -
              newp('Chatham', 'DPW', 11651),  -
          newp('Chatham', 'DPW', 11651),  -
              newp('Gotham', 'Fire', 41246))
          newp('Gotham', 'Fire', 41246))
   
   
    %so is object sortorder for object polis
%so is object sortorder for object polis
    %so = list(ascending(city), ascending(dept))
%so = list(ascending(city), ascending(dept))
    %lp:sort(%so)
%lp:sort(%so)
   
   
    %i is float
%i is float
    for %i from 1 to %lp:count
for %i from 1 to %lp:count
      print %lp(%i):myprint
  print %lp(%i):myprint
    end for
end for
   
   
    end
end
</pre>
</p>
   
   
The result is:
The result is:
<pre style="xmp">
<p class="output">Chatham (DPW): 11651
    Chatham (DPW): 11651
Chatham (Fire): 21940
    Chatham (Fire): 21940
Gotham (DPW): 33125
    Gotham (DPW): 33125
Gotham (Fire): 41246
    Gotham (Fire): 41246
Wareham (DPW): 5938
    Wareham (DPW): 5938
Wareham (Fire): 8444
    Wareham (Fire): 8444
</p>
</pre>
 
===Searching a collection===
==Searching a collection==
As of ''Sirius Mods'' version 7.6, a variety of methods are common to all the
<!-- As of <var class="product">Sirius Mods</var> version 7.6 -->A variety of methods are common to all the
collection classes for the purpose of searching a collection for
collection classes for the purpose of searching a collection for
the item(s) that satisfy one or more specified conditions.
the item(s) that satisfy one or more specified conditions.
   
   
===The searching methods===
The searching methods (all functions, listed below) have the same, or nearly
The searching methods (all functions, listed below) have the same, or nearly
the same syntax.
the same syntax. They take two parameters:
They take two parameters:
<ul>
<ul>
<li>An object that specifies the search conditions
<li>An object that specifies the search conditions
(a <tt>SelectionCriterion</tt> object, added in ''Sirius Mods'' 7.6).
(a <var>SelectionCriterion</var> object<!-- , added in <var class="product">Sirius Mods</var> 7.6 -->).
<li>A parameter (<tt>Start</tt>) that specifies where in the collection to
 
begin the search.
<li>A parameter (<var>Start</var>) that specifies where in the collection to
One method, SubsetNew, does not accept this parameter.
begin the search. One method, <var>SubsetNew</var>, does not accept this parameter.
</ul>
</ul>
   
   
Line 814: Line 756:
<dl>
<dl>
<dt>FindNextItem
<dt>FindNextItem
<dd>Searching &ldquo;forward&rdquo; in the collection,
<dd>Searching "forward" in the collection, finds the next item that matches a criterion, and returns that item.
finds the next item that matches a criterion, and returns that item.
 
<dt>FindPreviousItem
<dt>FindPreviousItem
<dd>Searching &ldquo;backward&rdquo; in the collection,
<dd>Searching "backward" in the collection, finds the next item that matches a criterion, and returns that item.
finds the next item that matches a criterion, and returns that item.
 
<dt>FindNextItemNumber
<dt>FindNextItemNumber
<dd>Searching &ldquo;forward,&rdquo;
<dd>Searching "forward," finds the next item that matches a criterion, and returns that item number.
finds the next item that matches a criterion, and returns that item number.
 
<dt>FindPreviousItemNumber
<dt>FindPreviousItemNumber
<dd>Searching &ldquo;backward,&rdquo;
<dd>Searching "backward," finds the next item that matches a criterion, and returns that item number.
finds the next item that matches a criterion, and returns that item number.
 
<dt>SubsetNew
<dt>SubsetNew
<dd>Returns a new collection that contains all the items in
<dd>Returns a new collection that contains all the items in the input collection that match the criterion.
the input collection that match the criterion.
</dl>
</dl>
   
   
The FindNextItem and FindPreviousItem methods also throw an <tt>ItemNotFound</tt>
The <var>FindNextItem</var> and <var>FindPreviousItem</var> methods also throw an <var>
exception ([[??]] refid=itemnfe.) if no item matches the SelectionCriterion.
[[ItemNotFound class|ItemNotFound]]</var>
exception if no item matches the <var>SelectionCriterion</var>.
   
   
A [[SelectionCriterion class|SelectionCriterion]] object,
===SelectionCriterion objects===
which might consist of multiple components, describes a
A <var>[[SelectionCriterion class|SelectionCriterion]]</var> object,
single selection criterion.
which might consist of multiple components, describes a single selection criterion.
For example, the <tt>GE</tt> method in that class uses two parameters to form a
For example, the <var>Ge</var> method in that class uses two parameters to form a
(&ldquo;greater than or equal to&rdquo;) comparison criterion to apply to the
("greater than or equal to") comparison criterion to apply to the collection items.
collection items.
So, for <var>SelectionCriterion</var> object <code>%sel</code>,
So, for SelectionCriterion object <tt>%sel</tt>,
which selects items whose absolute value is less than or equal to 1000, you might have:
which selects items whose absolute value is less than or equal to 1000,
<p class="code">%sel = ge(absolute, 1000)
you might have:
</p>
<pre style="xmp">
    %sel = ge(absolute, 1000)
</pre>
   
   
A simple search, starting from the eighth item in the %payoff Arraylist,
A simple search, starting from the eighth item in the %payoff <var>Arraylist</var>,
might be:
might be:
<pre style="xmp">
<p class="code">%item = %payoff:findNextItem(%sel, start=7)
    %item = %payoff:findNextItem(%sel, start=7)
</p>
</pre>
   
   
The parameters of the SelectionCriterion GE method above provide the operands
The parameters of the <var>SelectionCriterion</var> <var>Ge</var> method above provide the operands
for the comparison operator GE.
for the comparison operator <var>Ge</var>.
In this case the intrinsic Float [[Absolute (Float function)|Absolute]] function
In this case the intrinsic <var>Float</var> <var>[[Absolute (Float function)|Absolute]]</var> function
is applied to an item value.
is applied to an item value.
In general, this must be a function that operates on the type of the items
In general, this must be a function that operates on the type of the items
in the collection, and it may be a local method or method variable or a class
in the collection, and it may be a local method or method variable or a class member (variable, property).
member (variable, property).
   
   
The value that results from applying the Absolute method above is compared to
The value that results from applying the <var>Absolute</var> method above is compared to
the second GE parameter, 1000.
the second <var>Ge</var> parameter, 1000.
This 1000 may be any User Language intrinsic expression, such as a string or numeric
This 1000 may be any <var class="product">SOUL</var> intrinsic expression, such as a string or numeric literal.
literal.
   
   
In the fragment that follows, the function in the SelectionCriterion is a local method,
In the fragment that follows, the function in the <var>SelectionCriterion</var> is a local method, and the searching method, <var>FindPreviousItemNumber</var>, searches
and the searching method, <tt>FindPreviousItemNumber</tt>, searches
backward starting with the tenth item in the collection to find the item
backward starting with the tenth item in the collection to find the item
number of the first item that satisfies the criterion:
number of the first item that satisfies the criterion:
<pre style="xmp">
<p class="code">%flt is  arraylist of float
    %flt is  arraylist of float
%sel is object selectionCriterion for float
    %sel is object selectionCriterion for float
   
   
    local function (float):myMod is float
local function (float):myMod is float
      return %this:mod(7)
  return %this:mod(7)
    end function
end function
   
   
    %sel = LT(myMod, 1)
%sel = LT(myMod, 1)
    %num = %flt:findPreviousItemNumber(%sel, start=11)
%num = %flt:findPreviousItemNumber(%sel, start=11)
</pre>
</p>
   
   
The local method <tt>myMod</tt> above, which calls the [[Mod (Float function)|Mod]] method,
The local method <code>myMod</code> above, which calls the <var>[[Mod (Float function)|Mod]]</var> method, is necessary in this case because the <var>SelectionCriterion</var>
is necessary in this case because the SelectionCriterion
function parameter may not itself specify a parameter.
function parameter may not itself specify a parameter.
The function parameter is a method value, not a User Language expression.
The function parameter is a method value, not a <var class="product">SOUL</var> expression.
   
   
The preceding example also shows a SelectionCriterion object declaration,
The preceding example also shows a <var>SelectionCriterion</var> object declaration,
which must suit the item type to which the criterion will be applied,
which must suit the item type to which the criterion will be applied,
as described in
as described in [[SelectionCriterion class#Declaring a SelectionCriterion object variable|Declaring a SelectionCriterion object variable]].
"[[SelectionCriterion class#Declaring a SelectionCriterion object variable|Declaring a SelectionCriterion object variable]]".
   
   
In the following example, the
In the following example, the function parameter is the very useful identity function, <var>This</var>, which returns the value of the item to which it is applied.
function parameter is the very useful identity function, <tt>This</tt>,
The searching method <var>SubsetNew</var> returns a collection of all
which returns the value of the item to which it is applied.
The searching method <tt>SubsetNew</tt> returns a collection of all
the items in the collection that satisfy either of the criteria
the items in the collection that satisfy either of the criteria
(< 0, > 999) that comprise the <tt>OR</tt> criterion:
(< 0, > 999) that comprise the <var>Or</var> criterion:
<pre style="xmp">
<p class="code">%sel = OR(LT(this, 0), GT(this, 999))
    %sel = OR(LT(this, 0), GT(this, 999))
%arraylist = %flt:findPreviousItemNumber(%sel, start=11)
    %arraylist = %flt:findPreviousItemNumber(%sel, start=11)
</p>
</pre>
   
   
Usage notes:
===Using the searching methods===
<ul>
<ul>
<li>The main benefit of these searching methods is is the ease of coding provided by
<li>The main benefit of these searching methods is is the ease of coding provided by
their simplicity and flexibility.
their simplicity and flexibility.
However, the Find and Subset operations
However, the <var>Find</var> and <var>Subset</var> operations
on collections of objects will necessarily be considerably more expensive than the
on collections of objects will necessarily be considerably more expensive than the
comparable operations on $lists or Stringlists.
comparable operations on <var>Stringlists</var>.
<p>
For example, a level of
For example, a level of indirection between object references and objects makes the processing much more complicated than that for <var>Stringlists</var>.
indirection between object references and objects makes the processing much
However, because the cost of locates or subsets is likely to be a small fraction of the cost of most applications, switching to objects for these applications offers the benefits
more complicated than that for Stringlists.
of cleaner code without a major expense.</p></li>
However, because the cost of
 
locates or subsets is likely to be a small fraction of the cost of most
<li>The <var>FindNextItem</var> and <var>FindPreviousItem</var> methods throw an
applications, switching to objects for these applications offers the benefits
<var>ItemNotFound</var> exception if no item matches the <var>SelectionCriterion</var>, but
of cleaner code without a major expense.
the <var>FindNextItemNumber</var> and <var>FindPreviousItemNumber</var> methods ''do not''
<li>The FindNextItem and FindPreviousItem methods throw an
ItemNotFound exception if no item matches the SelectionCriterion, but
the FindNextItemNumber and FindPreviousItemNumber methods ''do not''
throw an exception in that case.
throw an exception in that case.
The following are the suggested guidelines for using these methods:
The following are the suggested guidelines for using these methods:
<ul>
<ul>
<li>For simply checking if an item in a collection matches a
<li>For simply checking if an item in a collection matches a
SelectionCriterion, use FindNextItemNumber or FindPreviousItemNumber.
<var>SelectionCriterion</var>, use <var>FindNextItemNumber</var> or <var>FindPreviousItemNumber</var>.</li>
<li>For looping over a collection, use FindNextItemNumber or FindPreviousItemNumber
 
with an If test.
<li>For looping over a collection, use <var>FindNextItemNumber</var> or <var>FindPreviousItemNumber</var>
with an <var>If</var> test.</li>
 
<li>For extracting a single item that you are very sure must be in the
<li>For extracting a single item that you are very sure must be in the
collection, use FindNextItem or FindPreviousItem.
collection, use <var>FindNextItem</var> or <var>FindPreviousItem</var>.
If you are wrong about the presence of the item,
If you are wrong about the presence of the item,
the exception is thrown and the request is cancelled.
the exception is thrown and the request is cancelled.</li>
 
<li>For conditionally extracting a single item from a collection, use
<li>For conditionally extracting a single item from a collection, use
FindNextItem or FindPreviousItem with a Try/Catch clause.
<var>FindNextItem</var> or <var>FindPreviousItem</var> with a <var>Try</var>/<var>Catch</var> clause.</li>
</ul>
</ul>
<p>
As a general footnote, a Try/Catch clause is actually more efficient than an
As a general footnote, a <var>Try</var>/<var>Catch</var> clause is actually more efficient than an
If test.
<var>If</var> test.
The Try does not produce any compiled code, and the Catch is only evaluated
The <var>Try</var> does not produce any compiled code, and the <var>Catch</var> is only evaluated
if there is an exception.
if there is an exception.
Try/Catch therefore executes no code other than what you are
<var>Try</var>/<var>Catch</var> therefore executes no code other than what you are
trying, whereas If has to also to execute the If.
trying, whereas <var>If</var> has to also to execute the conditional test.</p></li>
</ul>
 
==See also==
<ul>
<li>[[Method variables]]
<li>[[Object oriented programming in SOUL]]
</ul>
</ul>
<table class="list"><tr>
<td valign="top"><ul style="margin-top:0px;"><span id="collectionClasses"></span>
<li>[[Arraylist class]]
<li>[[FloatNamedArraylist class]]
<li>[[NamedArraylist class]]
<li>[[UnicodeNamedArraylist class]]
</ul></td>
<td valign="top"><ul style="margin-top:0px;">
<li>[[List of Arraylist methods]]
<li>[[List of FloatNamedArraylist methods]]
<li>[[List of NamedArraylist methods]]
<li>[[List of UnicodeNamedArraylist methods]]
<li>[[List of Collection methods]]
</ul></td>
<td valign="top"><ul style="margin-top:0px;">
<li>[[Arraylist methods syntax]]
<li>[[FloatNamedArraylist methods syntax]]
<li>[[NamedArraylist methods syntax]]
<li>[[UnicodeNamedArraylist methods syntax]]
</ul></td>
</tr>
</table>
[[Category:Overviews]]
[[Category:Overviews]]
[[Category:System classes]]
[[Category:System classes]]
[[Category:SOUL object-oriented programming topics]]

Latest revision as of 21:01, 26 August 2015

It is common in programming to have groups of things that all have some common characteristic and are used fairly interchangeably. For example, one might have a number of items in an order, or a parent might have a number of children. Traditionally, this type of processing is dealt with using arrays. Traditional User Language arrays are enhanced by SOUL in Model 204 V7.5 to include support for arrays of structures and objects.

Arrays, however, have some limitations:

  • They are static. That is, array instances and their size are set at compile-time.
  • There are relatively few things you can do with an array. Typically, you are limited to setting and retrieving the value of an array item.

Since both of these problems with arrays do not apply to objects, another way to view the problem with arrays is that they are not objects, As a remedy, SOUL has a special kind of object that is very much like an array but has all the advantages of an object. These objects are called collections.

Many other object-oriented languages also have a concept of collections or collection objects but with a slight difference: object-oriented languages that have collection objects usually implement them as collections of generic objects, that is objects with no compile-time class (or more accurately, a very generic class). While this provides much flexibility, it also defeats one of the advantages of traditional arrays — compile-time knowledge of the array element datatypes — so it sacrifices compile-time error checking and more efficient compiled code.

The SOUL implementation of typed collections provides the best of both worlds: collection objects along with compile-time declaration of the type of the collection elements.

Collection object declaration syntax

{variable} [Is] [Collection] - collectionType Of [collectionType Of] type - [ Global [(globalName)] ]

variable The name of the object variable that refers to a collection of the indicated type. If outside a class declaration block and structure, the variable must begin with a percent sign. If inside a structure declaration, the variable must not begin with a percent sign. If inside a class declaration block, the variable cannot start with a percent sign and must be preceded by the word Variable.
collectionType The name of one of the system collection classes (Arraylist, NamedArraylist, FloatNamedArraylist, UnicodeNamedArraylist). Since collections are always system classes, these names may be preceded with System:.
type Any basic SOUL datatype, including String (with a length and optional DP), Fixed (with an optional DP), Float, Longstring, Unicode, and Object (followed by the object class).

Arrays and structures are not supported as collection items, but collections can themselves be collection items. If type is a collection, you specify both the collection and item datatypes. For example: Arraylist of string len 16

globalname The optional global name if the collection variable is not a class or structure variable. If Global is specified without globalName, the name of the variable without a percent sign is used as the global name.

Collection object declarations do not contain parameters for size or for number of items. The number of items in a collection is completely dynamic, so no arbitrary limit needs to be set on their size (although SOUL will not support collections with more than 2**31, or about 2 billion, items).

Collections have one VTBL/STBL slot to hold a single collection element, and all other collection items are kept in CCATEMP.

Note: For a collection of objects, it is the object references that are kept in CCATEMP, not the actual objects. So even though only one object reference in the collection will be in VTBL, many of the objects referenced in the collection may be in VTBL/STBL. The collection item in VTBL/STBL is the last referenced item, and an immediately subsequent reference to that same item will use the item directly from VTBL/STBL rather than loading it from CCATEMP. For this reason, consecutive references to the same collection item are quite efficient.

Here are sample collection object declarations:

%scores is collection arraylist of float %costs is arraylist of fixed dp 2 %basket is floatNamedArraylist of object order %staff is collection unicodeNamedArraylist of string len 64 %value is namedArraylist of namedArraylist of longstring

Coding considerations for collections

Although collections vary by collection type, they are more alike than they are different. The remainder of this article contains topics that address features and methods common to all the collection types. The characteristics and methods of each individual collection type are described in separate articles; links to those groups of articles are contained in the "See also" section below.

Operating on collection items

All collections have at least the two standard properties described below.

Count Number of items in collection.
Item A specific item in the collection.

The Item property always takes at least one parameter indicating which item is being referenced, though the type of the parameter can vary with the collection class.

Some collection classes allow references to items that have not been added to the collection with some other method; other collection classes do not, and cause a request cancellation on such a reference.

The Item property can be both set and retrieved in all collections.

The following example illustrates a simple use of the Count and Item properties:

%scores is collection arraylist of float ... %scores = new ... for %i from 1 to %scores:count %scores:item(%i) = %scores:item(%i) + 10 end for

The Item property name may be left off:

for %i from 1 to %scores:count %scores(%i) = %scores(%i) + 10 end for

If the %scores Arraylist is just one of the members to be updated in the %allScores collection of Arraylists, you might have consecutive omissions of the Item name (%allScores(%i)(%j)):

for %i from 1 to %allScores:count for %j from 1 to %allScores(%i):count %allScores(%i)(%j) = %allScores(%i)(%j) + 10 end for end for

Explicitly specifying the method name Item, is not required because:

  • It is very convenient to omit it, since the Item property is so heavily used.
  • The Item property always has at least one parameter, so a collection name followed by a parenthesis can be taken to clearly imply the Item property.
  • It facilitates conversion of existing arrays to collections.

Collections also have methods that depend on the collection types. The methods associated with the SOUL collection types (Arraylist, NamedArraylist, FloatNamedArraylist, UnicodeNamedArraylist) are described in subsequent sections.

In the descriptions of the methods, the term item means a value or variable of the same type as specified on the collection declaration, or a value or variable convertible to that type. For example, if a collection is declared as:

%stooges is arraylist of object stooge

An Add method applied to %stooges can only add an object of class stooge:

%moe is object stooge ... %stooges:add(%moe)

On the other hand, if a collection is declared as

%value is Arraylist of string len 16

you can add anything that can be converted to a string:

%long is longstring ... %value:add('A string') %value:add(22) %value:add(%long)

Note: In the example above, as is usual with longstrings, a truncation of the longstring on addition would cause a request cancellation error.

Comparing and assigning new collection variables

Collection variables, being a special variety of object variables, can be assigned to each other and compared, just like other object variables:

%alist is arraylist of longstring %blist is arraylist of longstring ... %blist = %alist ... if %alist eq %blist then

For assignment or comparison to be allowed, however, both the collection type (Arraylist, for example) and the collection item datatype must be identical. As just two examples, you cannot assign the contents of an Arraylist variable to a NamedArraylist variable, and you cannot assign the contents of an arraylist of longstring to an arraylist of float.

Note:

When assigning to a collection variable and using the syntax of the New function that explicitly indicates the class for collections, both the collection and item datatypes must be specified just as on the collection variable declaration:

%alist is collection floatNamedArraylist of longstring %alist = %(floatNamedArraylist of longstring):new

Printing a collection

Formerly, the standard way to view the entire contents of a collection was to loop through the list items and display each one using a SOUL Print statement (or Audit or Trace). For a NamedArraylist, for example, you used a method for the item subscript name and a method for the item content:

%nal is namedArraylist of float ... %nal = new %nal('Chicago') = 22 %nal('New York') = -999 %nal('Los Angeles') = 3.1415926 %nal('Philadelphia') = 1099 for %i from 1 to %nal:count print %nal:nameByNumber(%i) and %nal:itemByNumber(%i) end for

This is the result:

Chicago 22 Los Angeles 3.1415926 New York -999 Philadelphia 1099

Now, the Print method for any collection does the work of the loop in the preceding example, and more. Supplied for debugging purposes, Print (or the essentially identical Audit or Trace method) would produce the following output using the example collection above (that is: %nal:print):

1: Chicago: 22 2: Los Angeles: 3.1415926 3: New York: -999 4: Philadelphia: 1099

Notice that Print outputs all the collection items (or, optionally, a range of items), and it also includes:

  • The ordinal, or position, number for each item
  • A separator string after the item position number and also after the item name (if a named collection)

Print also has optional parameters that let you specify:

  • The lengths for the item name and number
  • A label string to precede each output line
  • The number of items to display

Note:

The Print method applies a ToString method (by default) to each item value (and always to each item name), to produce its result. Applying Print to a collection whose item types are not system classes will work only if at least one of the following is true:

  • The user class contains a ToString method.
  • The Print method includes an appropriate "method parameter," as described below.

General syntax of Print (Audit or Trace) for a collection

%coll:Print (method, numWidth, nameWidth, - separator, start, maxItems, label)

All parameters are optional and all except method have required names (which match the names used in the syntax above). The parameters are described briefly below and in greater detail in the individual method descriptions for the appropriate collection type.

method The method applied to collection items to produce the printed output.

The method must take no parameters and produce an intrinsic (Float, String, Fixed, Unicode) value. It may be a system or user-written method, a class variable or property, a

local method, or a method variable. The default is the ToString method.
numWidth The number of bytes for the item number in the output. If 0, the default, the item number is not printed.
nameWidth The number of bytes for the item name (ignored if an Arraylist). If -1, the default, the entire name is fit exactly. If 0, the item name is not printed.
separator A string that follows the item number and that repeats after the item name. The default is a colon. A blank follows each instance of separator.
start The number of the collection item from which to start the output display. By default, the display begins from item one.
maxItems The maximum number of collection items to print. By default, all items are displayed.
label A string, null by default, marking the beginning of each item's line of output.

Examples using width or local method arguments

For the NamedArraylist in the first example in "Printing a collection", but issuing %nal:print(numWidth=3, nameWidth=14), this is the result:

1: Chicago  : 22 2: Los Angeles  : 3.1415926 3: New York  : -999 4: Philadelphia  : 1099

If you issue %nal:print(numWidth=3, nameWidth=7), the result is:

1: Chicago: 22 2: Los Ang: 3.1415926 3: New Yor: -999 4: Philade: 1099

You can define a local function to display your output:

local function (string):quote is longstring return '''' with %this with '''' end function

Now you issue:

%nal:print(quote)

And you get this result:

1: Chicago: '22' 2: Los Angeles: '3.1415926' 3: New York: '-999' 4: Philadelphia: '1099'

If you named your local method toString instead of quote, it would not need to be specified on the Print method. This is shown in the following example.

Examples using class or local ToString

In the following request, the method parameter used with the Arraylist Print method is a class variable:

b class python public variable surname is string len 30 variable givenName is string len 30 variable routine is string len 30 constructor new(%surname is string len 30, - %givenName is string len 30, - %routine is string len 30) end public constructor new(%surname is string len 30, - %givenName is string len 30, - %routine is string len 30) %this:surname = %surname %this:givenName = %givenName %this:routine = %routine end constructor end class %pythons is arraylist of object python %pythons = list(new('Cleese', 'John', 'Dead Parrot'), - new('Palin', 'Michael', 'Lumberjack'), - new('Idle', 'Eric', 'Nudge nudge'), - new('Chapman', 'Graham', 'Throat Wobbler Mangrove'), - new('Jones', 'Terry', 'Mouse Organ')) %pythons:print(surname) end

The request result is:

1: Cleese 2: Palin 3: Idle 4: Chapman 5: Jones

If you create the following ToString method in the class:

function toString is longstring return 'surname=' with %this:surname with ', ' with - 'givenName=' with %this:givenName with ', ' with - 'routine=' with %this:routine end function

And you issue this Print method call, which implicitly invokes your toString method:

%pythons:print(start=2, maxItems=3)

The result is:

2: surname=Palin, givenName=Michael, routine=Lumberjack 3: surname=Idle, givenName=Eric, routine=Nudge nudge 4: surname=Chapman, givenName=Graham, routine=Throat Wobbler Mangrove

Examples of subscript display format for named collections

When printing the name subscript for a NamedArraylist, the subscript is left as is. For a FloatNamedArraylist, the Float subscripts are displayed as strings. For a UnicodeNamedAraylist, the Unicode subscripts are translated from Unicode to EBCDIC, (character-entity-encoding any non-translatable characters), as in the following:

%transcendental is unicodeNamedArraylist of float ... %transcendental = new %transcendental('&pi;':U) = 3.1415926 %transcendental:print

The Print result shows the encoded form of the Unicode item name:

1: &#x03C0;: 3.1415926

Note: If you specified %transcendental:print(namewidth=4), for example, the item name is truncated:

1: &#x: 3.1415926

Finding collection maxima and minima, and sorting

In addition to Count and Item methods, all collections also have Maximum and Minimum methods. These are methods that let you find the collection item that returns the highest or lowest value, respectively, for the attribute you want to evaluate. That attribute must be in the form of a function you specify that is defined to operate on the type of items in the collection and to return a simple string or numeric value.

Arraylist and NamedArraylist collections also have sorting methods that are similar to Maximum and Minimum but which sort a collection by the attribute function you specify.

What distinguishes the maximum/minimum and sorting methods is:

  • The use of a function you specify as a parameter to apply to the collection items
  • The variety of types of function parameter you can specify

The following series of examples introduces the maximum/minimum and sorting methods and displays many of the types of function parameter you can implement.

Finding a maximum using a system method parameter

In the following request, the Maximum method first applies the Stringlist Count function to each item in an Arraylist of Stringlist items. The Count function is specified as a parameter to the Maximum method. Maximum then returns the position in the Arraylist of the Stringlist that has the most items. The List function simplifies the construction of the lists.

b %I is float %list1 is object stringlist %list2 is object stringlist %list3 is object stringlist %list1 = List('the', 'quick', 'brown') %list2 = List('fox', 'jumped', 'over', 'the') %list3 = List('lazy', 'dog', 'yesterday', 'two', 'times') %arrayl is collection arraylist of object stringlist %arrayl = List(%list1, %list2, %list3) print 'The longest list is item ' %arrayl:maximum(count) end

The result is:

The longest list is item 3

Finding a minimum using a class Variable parameter

The function you apply to the collection items is not restricted to system class methods. More precisely, the function parameter is a method value: it can be the name of a system method, as above, or a user method or local method. Or the function parameter can be a Function variable, including a class Variable or Property. Any of these types of method value are valid as long as they a) operate on the item type in the collection, and b) return an intrinsic (number, string, unicode) value.

In the following example, the Minimum method applies a class variable to determine the Arraylist item with the minimum value. The List function simplifies the construction of the Arraylist.

b class python public variable firstname is string len 16 variable surname is string len 16 variable birthdate is float constructor newpy (%sname is string len 16, - %name is string len 16, %bd is float) end public constructor newpy (%sname is string len 16, - %name is string len 16, %bd is float) %this:firstname = %name %this:surname = %sname %this:birthdate = %bd end constructor end class %lp is arraylist of object python %lp = list(newpy('Gilliam', 'Terry', '19401122'), - newpy('Cleese', 'John', '19391027'), - newpy('Idle', 'Eric', '19430329'), - newpy('Palin', 'Michael', '19430505'), - newpy('Chapman', 'Graham', '19410108'), - newpy('Jones', 'Terry', '19420201') ) print 'Item ' %lp:minimum(birthdate) ' has eldest Python' end

The result is:

Item 2 has eldest Python

Sorting an Arraylist using one sort criterion

The Arraylist of python objects above can be readily sorted by birthdate as well. The Arraylist Sort and SortNew methods take as input the sorting criteria, a combination of a sorting order direction (Ascending or Descending) and its sort key parameter (a function just like that in Maximum/Minimum which operates on the collection items). This direction and sort key combination is also known as a SortOrder.

For example, to sort the Arraylist of python objects in ascending order by birthdate, you can use the Sort subroutine:

call %lp:sort(ascending(birthdate))

Or you can use the SortNew function:

%lp = %lp:sortnew(ascending(birthdate))

If you provide the python class with a method to print a python object, then loop through the sorted Arraylist returned by SortNew:

class python ... function myprint is longstring return %this:firstname with ' ' with - %this:surname with ' ' with - '(born: ' with %this:birthdate with ')' end function end class ... %i is float %lp = %lp:sortnew(ascending(birthdate)) for %i from 1 to %lp:count print %lp(%i):myprint end for

This is the sorted result:

John Cleese (born: 19391027) Terry Gilliam (born: 19401122) Graham Chapman (born: 19410108) Terry Jones (born: 19420201) Eric Idle (born: 19430329) Michael Palin (born: 19430505)

Note: Of the collection classes, only the Arraylist class contains a Sort subroutine; all the collection classes have a SortNew function.

Finding minima using a method variable parameter

The function-like method value parameter in Maximum, Minimum, and sorting may be a method variable. %meth in the following simple example is assigned in turn to two local functions:

b %meth is function (string):func is longstring Local function (string):leftmost is longstring return %this:left(1) end function Local function (string):rightmost is longstring return %this:right(1) end function %l is arraylist of string len 30 %l = list('Hickory', 'Dickory', 'Doc') %meth = rightmost print %l:minimum(%meth) %meth = leftmost print %l:minimum(%meth) end

This request prints the number of the item that has the rightmost character that is alphabetically the earliest, then the number of the item that has the leftmost character that is the earliest (and closer to the beginning of the list):

3 2

Note: Specifying the local functions themselves as the Minimum method parameter in the preceding example would also produce the same result. For example, the first print %l:minimum(%meth) call in the example is equivalent to print %l:minimum(rightmost).

However, explicitly specifying right(1) (the method and argument that local function rightmost invokes) as the Minimum parameter does not work. Specifying a method that itself requires a parameter as the Minimum (or Maximum or sort) parameter is a syntax violation and compilation error. The parameter for Minimum is a method value, not a SOUL expression. You can use a local function as the Minimum parameter, as in the example above, to apply a method that requires an argument.

Using the This function as the Maximum parameter

Finding the Maximum, Minimum, and sorting are likely to be very common operations on collections of SOUL intrinsic values. In these cases, you want the function parameter for the maximum/minimum and sorting methods to be an identity function like in the following:

b %l is arraylist of float %l = list(9, 11, 4, -5, 17, 3, 4, 6) local function (float):thisVal is float return %this end function printText Item {%l:maximum(thisVal)} has the maximum value end

To simplify such requests, a special method value provides the identity function for intrinsic classes. The method value (named This) simply returns the value of the method object. It is valid only for intrinsic classes.

Using This, the previous request becomes:

b %l is arraylist of float %l = list(9, 11, 4, -5, 17, 3, 4, 6) printText Item {%l:maximum(this)} has the maximum value end

Since This is the default method value for the maximum/minimum/sorting function parameter, %l:maximum(this) above can be replaced by:

%l:maximum

And sort(descending(this)), for example, can be replaced by:

%l:sort(descending)

Sorting an Arraylist using two sort criteria

The following request sorts an Arraylist by two sort criteria. A SortOrder object is explicitly defined to contain the sort criteria. The List function simplifies the construction of the Arraylist.

b class polis public variable city is string len 16 variable dept is string len 10 variable cost is float constructor newp (%city is string len 16, - %dp is string len 10, %cst is float) function myprint is longstring end public constructor newp (%city is string len 16, - %dp is string len 10, %cst is float) %this:city = %city %this:dept = %dp %this:cost = %cst end constructor function myprint is longstring return %this:city with ' (' with - %this:dept with '): ' with %this:cost end function end class %lp is arraylist of object polis %lp = list(newp('Gotham', 'DPW', 33125), - newp('Chatham', 'Fire', 21940), - newp('Wareham', 'Fire', 8444), - newp('Wareham', 'DPW', 5938), - newp('Chatham', 'DPW', 11651), - newp('Gotham', 'Fire', 41246)) %so is object sortorder for object polis %so = list(ascending(city), ascending(dept)) %lp:sort(%so) %i is float for %i from 1 to %lp:count print %lp(%i):myprint end for end

The result is:

Chatham (DPW): 11651 Chatham (Fire): 21940 Gotham (DPW): 33125 Gotham (Fire): 41246 Wareham (DPW): 5938 Wareham (Fire): 8444

Searching a collection

A variety of methods are common to all the collection classes for the purpose of searching a collection for the item(s) that satisfy one or more specified conditions.

The searching methods

The searching methods (all functions, listed below) have the same, or nearly the same syntax. They take two parameters:

  • An object that specifies the search conditions (a SelectionCriterion object).
  • A parameter (Start) that specifies where in the collection to begin the search. One method, SubsetNew, does not accept this parameter.

The searching methods are:

FindNextItem
Searching "forward" in the collection, finds the next item that matches a criterion, and returns that item.
FindPreviousItem
Searching "backward" in the collection, finds the next item that matches a criterion, and returns that item.
FindNextItemNumber
Searching "forward," finds the next item that matches a criterion, and returns that item number.
FindPreviousItemNumber
Searching "backward," finds the next item that matches a criterion, and returns that item number.
SubsetNew
Returns a new collection that contains all the items in the input collection that match the criterion.

The FindNextItem and FindPreviousItem methods also throw an ItemNotFound exception if no item matches the SelectionCriterion.

SelectionCriterion objects

A SelectionCriterion object, which might consist of multiple components, describes a single selection criterion. For example, the Ge method in that class uses two parameters to form a ("greater than or equal to") comparison criterion to apply to the collection items. So, for SelectionCriterion object %sel, which selects items whose absolute value is less than or equal to 1000, you might have:

%sel = ge(absolute, 1000)

A simple search, starting from the eighth item in the %payoff Arraylist, might be:

%item = %payoff:findNextItem(%sel, start=7)

The parameters of the SelectionCriterion Ge method above provide the operands for the comparison operator Ge. In this case the intrinsic Float Absolute function is applied to an item value. In general, this must be a function that operates on the type of the items in the collection, and it may be a local method or method variable or a class member (variable, property).

The value that results from applying the Absolute method above is compared to the second Ge parameter, 1000. This 1000 may be any SOUL intrinsic expression, such as a string or numeric literal.

In the fragment that follows, the function in the SelectionCriterion is a local method, and the searching method, FindPreviousItemNumber, searches backward starting with the tenth item in the collection to find the item number of the first item that satisfies the criterion:

%flt is arraylist of float %sel is object selectionCriterion for float local function (float):myMod is float return %this:mod(7) end function %sel = LT(myMod, 1) %num = %flt:findPreviousItemNumber(%sel, start=11)

The local method myMod above, which calls the Mod method, is necessary in this case because the SelectionCriterion function parameter may not itself specify a parameter. The function parameter is a method value, not a SOUL expression.

The preceding example also shows a SelectionCriterion object declaration, which must suit the item type to which the criterion will be applied, as described in Declaring a SelectionCriterion object variable.

In the following example, the function parameter is the very useful identity function, This, which returns the value of the item to which it is applied. The searching method SubsetNew returns a collection of all the items in the collection that satisfy either of the criteria (< 0, > 999) that comprise the Or criterion:

%sel = OR(LT(this, 0), GT(this, 999)) %arraylist = %flt:findPreviousItemNumber(%sel, start=11)

Using the searching methods

  • The main benefit of these searching methods is is the ease of coding provided by their simplicity and flexibility. However, the Find and Subset operations on collections of objects will necessarily be considerably more expensive than the comparable operations on Stringlists.

    For example, a level of indirection between object references and objects makes the processing much more complicated than that for Stringlists. However, because the cost of locates or subsets is likely to be a small fraction of the cost of most applications, switching to objects for these applications offers the benefits of cleaner code without a major expense.

  • The FindNextItem and FindPreviousItem methods throw an ItemNotFound exception if no item matches the SelectionCriterion, but the FindNextItemNumber and FindPreviousItemNumber methods do not throw an exception in that case. The following are the suggested guidelines for using these methods:
    • For simply checking if an item in a collection matches a SelectionCriterion, use FindNextItemNumber or FindPreviousItemNumber.
    • For looping over a collection, use FindNextItemNumber or FindPreviousItemNumber with an If test.
    • For extracting a single item that you are very sure must be in the collection, use FindNextItem or FindPreviousItem. If you are wrong about the presence of the item, the exception is thrown and the request is cancelled.
    • For conditionally extracting a single item from a collection, use FindNextItem or FindPreviousItem with a Try/Catch clause.

    As a general footnote, a Try/Catch clause is actually more efficient than an If test. The Try does not produce any compiled code, and the Catch is only evaluated if there is an exception. Try/Catch therefore executes no code other than what you are trying, whereas If has to also to execute the conditional test.

See also