Functions: conversion

You can define a conversion function to convert data from one type to another. It is possible to define an ordinary function to perform this operation:

  define string function i-to-s
   value integer x
   as
      return "d" % x
  
  process
     local integer foo initial {5}
     output i-to-s foo

A conversion function is different however. A conversion function is called automatically whenever a variable of one type is specified where data of another type is expected. For instance, the keyword output expects a variable of type stream and you will get a compile time error if you specify a variable of type integer:

  process
     local integer foo initial {5}
     output foo

Normally, you would have to format the integer value as a stream as follows:

  process
     local integer foo initial {5}
     output "d" % foo

However, if you specify a conversion function to convert an integer to a stream, you can output an integer variable without using the formatting operator directly:

  define string conversion-function
   value integer x
   as
      return "d" % x
  
  process
     local integer foo initial {5}
     output foo

Notice that the conversion function does not have a name. Since it is called implicitly by OmniMark and is not explicity named in your code, there is no reason for it to have a name. Because they are not named, you can only have one conversion function for each conversion type. And because OmniMark defines conversion functions for many common type conversions, you cannot define conversion functions for those conversions. For instance, OmniMark defines a conversion function from stream to integer, so you cannot define one of your own.

The above example notwithstanding, OmniMark provides all the conversion functions you reasonably need for the built-in OmniMark data types. OmniMark libraries that define opaque data types also provide all the conversion functions you reasonably need for working with those types and the built in OmniMark types. There are therefore only two reasons why you would likely need to define your own conversion functions:

  1. If you write an external function library containing new opaque data types.
  2. If you create your own data types using OmniMark records.

While you will seldom need to define a conversion function between different record types, it can be useful to define a conversion function from a record type to a stream, as this can allow you to output the value of a record simply by naming the record in the output action. The following program illustrates this technique:

  declare record day
   field integer day
   field integer month
   field integer year
  
  define string conversion-function
   value day d
   as
     local string  month-text initial
      {"January", "February", "March",
       "April", "May", "June", "July",
       "August", "September", "October",
       "November", "December"}
  
     return "d" % d:day
         || " "
         || month-text[d:month]
         || ", "
         || "d" % d:year
  
   process
      local day moon-landing
      set moon-landing:day to 20
      set moon-landing:month to 07
      set moon-landing:year to 1969
  
      output moon-landing