Initializing help system before first use

Unions

A union is a container capable of holding an object of one of a predefined set of types. One possible use of this functionality is for reading and storing input data of a-priori unknown type. It can also be helpful for advanced programming tasks involving retrieval of information from another Mosel model without prior knowledge of its structure/data model.

Defining unions

Defining an entity of a union type consists in specifying the set of compatible types or the predefined union type any than can handle any type without restriction.

 declarations
    u: string or real              ! Scalar accepting 'string' or 'real'
    a: any                         ! Entity accepting any type
  ! Defining a type name for the union of the 4 basic Mosel types:
    basictype = string or integer or real or boolean
    B: array(range) of basictype   ! Array of union type 'basictype'
 end-declarations

The first type that is specified for a union has a special meaning as it defines the representation to use when the union is initialized from some textual form, besides that, order has no impact. In the case of the predefined union type any the textual representation is handled by a string. If any of the specified compatible types is itself a union the resulting set of compatible types will include all types of this union.

The type of a union is determined when a value is assigned to the entity, it can be retrieved via gettypeid or using the operator is:

 declarations
    u: string or real              ! Scalar accepting 'string' or 'real'
  end-declarations
  u:="a"
  writeln(u, " is string: ", u.typeid = string.id)      ! Output:  true
  u:=7.5
  writeln(u, " is real: ", u.typeid = real.id)          ! Output:  true
 ! The preceding line is equivalent to:
  writeln(u, " is real: ", u is real)                   ! Output:  true 

It is possible to force a particular type in assignments. You need to employ the create procedure for types that do not support assignment such as 'mpvar':

 declarations
    a: any                         ! Entity accepting any type
  end-declarations
  a.real:=10
  writeln(a, ":", a is real, a is integer)      ! Output: true false
  a.text:="a text"
  writeln(a, ":", a is text, a is string)       ! Output: true false
  create(a.mpvar)
  writeln(getsol(a.mpvar), ":", a is mpvar)     ! Output: true

A union entity can be assigned a compatible union type, but if its type is not compatible with the destination of the assignment a runtime error will be raised. A wrapping mechanism is used when a subroutine expects a union but it receives a compatible type or a different union type:

 declarations
    u: string or real              ! Scalar accepting 'string' or 'real'
    a: any                         ! Entity accepting any type
  ! Defining a type name for the union of the 4 basic Mosel types:
    basictype = string or integer or real or boolean
    B: array(range) of basictype   ! Array of union type 'basictype'
 end-declarations

! This subroutine accepts any union type as its argument
 procedure dosomething(aunion: any)
   writeln("In procedure 1: ", aunion)
 end-procedure

 a:=date(2020,12,24); u:=7.5
 dosomething(a)
 dosomething(u)

! This subroutine only accepts compatible union types
 procedure dosomething2(aunion: basictype)
   writeln("In procedure 2: ", aunion)
 end-procedure

 a:=2; u:=7.5; B(1):="abc"
 dosomething2(a)      ! Type of 'a' now is integer, so it is compatible, but
                      ! this would fail with the previous type 'date' of 'a'
 dosomething2(u)      ! Types of 'u' are a subset of union 'basicvalue'
 dosomething2(B(1)) 

Initialization of unions from file

When initializing unions from text format data files only scalar values of basic types are considered. More precisely, integers, reals, and Booleans are assigned to the union; textual values are used to initialize the entity as if it was of the first compatible type of the union (for the union any this is a string). An I/O error will be raised if this type does not support initialization.

 declarations
   L: list of any                  ! List of type 'any'
   mytype = text or integer or real or boolean
   B: array(R:range) of mytype     ! Array of union type 'mytype'
   TNAME: array(integer) of text   ! Type names for display
 end-declarations

 initializations from "uniondata.dat"
   L  B
 end-initializations

 TNAME(integer.id):="integer"; TNAME(real.id):="real"
 TNAME(string.id):="string"; TNAME(text.id):="text"
 TNAME(boolean.id):="boolean"

 writeln("L=", L)
 forall(i in L) writeln("  ", i, ":", i.typeid, " ", TNAME(i.typeid))
 writeln("B=", B)
 forall(i in R)
   writeln("  B", i, "=", B(i),":", B(i).typeid, " ", TNAME(B(i).typeid))

Assuming the data file 'uniondata.dat' has this contents:

L: [10 "abc" true 7.5]
B: [(1) "abc" (3) 5 (4) 5.6 ]

then the code snippet above will produce the following output:

L=[10,abc,true,7.5]
  10:1 integer
  abc:3 string
  true:4 boolean
  7.5:2 real
B=[abc,?,5,5.6]
  B1=abc:11 text
  B2=?:-1
  B3=5:1 integer
  B4=5.6:2 real

When exporting unions, any non-scalar value or types that do not support conversion to string will result in a NIL value ('?' in text format files) in the generated file. Appending the following lines to the previous example

 declarations
   x: mpvar
 end-declarations
 L+= [any(x)]

 initializations to "unionout.dat"
   L  B
 end-initializations

will result in an output file 'unionout.dat' with this contents:

L: [10 abc true 7.5 ?]
B: [(1) abc ? 5 5.6]

© 2001-2021 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.