SIMPOL Documentation

Object Operators

Object operators are represented by the property operator also known as the dot operator (.) and the member operator also known as the shriek, bang, or exclamation point operator (!). The property operator is used to access the properties and methods of an object. This is similar to the way it is used in numerous other languages. The member operator is used to access member information in a related member of the object in a way that is specific to the data type in use, athough it is similar to accessing a member of a collection in other languages. The best way to illustrate the use of the member operator is with a few examples:

function main()
  integer iErrnum
  ppcstype1 ppcs
  ppcstype1file f
  ppcstype1field sfldLastname
  ppcstype1record r
  boolean bFound
  string sResult

  // Initialize iErrnum so that it refers to an object rather than
  // to .nul
  iErrnum = 0
  // Initialize ppcs to use a port and act as a user called test
  ppcs =@ ppcstype1.new(udpport=1289, error=iErrnum, \
                        username="test")
  // If the initialization succeeded ...
  if ppcs !@= .nul
    // Open the file CUSTS at www.superbase.co.uk on port 1280
    f =@ ppcs.openudpfile("www.superbase.co.uk:1280", "CUSTS", \
                          error=iErrnum)

    // If the file opened successfully ...
    if f !@= .nul
      // Retrieve a reference to the field in the CUSTS file whose
      // name is Lastname. Please note that if there is no field
      // called Lastname this will result in an untrappable error.
      // If there is any concern that a field may not be present,
      // it would be better to use the function getfield() from
      // the db1util.sml library file since that will return .nul
      // rather than causing an error. This reference in both
      // cases is case-sensitive. If the field contains any
      // characters that are not valid in an identifier then it
      // should be placed in double-quotes. Variable references
      // are not permitted as the argument following the member
      // operator.
      sfldLastname =@ f!Lastname

      // Initialize the bFound variable to refer to an object
      // instead of .nul
      bFound = .false

      // Assign the results of the lookup of the value Smith in
      // the Lastname index to the r variable. Since we passed the
      // error and found objects in the function will return the
      // nearest record even in the case of an inexact match.
      r =@ sfldLastname.index.selectkey("Smith", error=iErrnum, \
                                        found=bFound)

      // Test that the r variable points to an object (if the file
      // were empty it would return a .nul object
      if r !@= .nul
        // Assign the value contained in the ppcstype1record
        // object referred to by r that is referenced by the
        // Lastname field of the file object. This can also be
	      // done by using the get() method of the record object.
        // Again, if there is no field called Lastname (case-
        // sensitive) in the file then this assignment will result
	      // in an untrappable runtime error.
        sResult = r!"Lastname"
      end if
    end if
  end if
end function sResult

As can be seen from the example above, there are different operations taking place when the member operator is used depending upon the type with which it is used. In the first case, the argument to the member operator is used to lookup a field name in the ring of fields and to return a reference to a field object which must be assigned using the @= operator. In the second case, a much more complex operation is taking place. The argument to the member operator is being used to lookup a field reference in the file object reference that is part of the record object and that is then used as an argument to the get() method of the record object.

In every case, the member object is used to provide a type of shorthand that results in a logical assignment of what otherwise might be a number of programmatic steps. As was stated in the remarks in the example, any error will result in an untrappable runtime error that will halt the program. Also, the overhead for using this approach is normally higher than using the more mundane approach and in some cases may need optimization using the alternative method if the section of code is too slow. That is because this requires a lookup each time rather than doing the lookup once and storing the result, so in a loop the cost of doing the lookup over and over again can make itself felt.