Switching to mmreflect
Switching from 'xreflect' to 'mmreflect'
The module mmreflect now provides functional equivalence to xreflect (the latter is now deprecated), however, the usage of individual features is different given that the implementation of mmreflect relies on the recently introduced concept of unions and the possibility to work with subroutine references. The following listing compares the implementation of specific programming tasks with these two modules, using the examples from the xreflect manual. It should be noted that the functionality provided by mmreflect is more generic than the cases discussed here which focus on the portion of its functionality that matches what is accessible through xreflect. In particular, by working with unions there are no restrictions on the types or data structures that can be handled through mmreflect.
All functionality of the module xreflect is defined within the namespace xreflect to avoid clashes with functionality of the same name in mmreflect, the following code examples assume that namespace search has been specified for xreflect:
| xreflect | mmreflect |
|---|---|
uses "xreflect" nssearch xreflect |
uses "mmreflect" |
The type 'basicvalue'
The module xreflect defines the type basicvalue for scalar values of Mosel types boolean, integer, real, string, text. The implementation of mmreflect relies on standard Mosel union types that work with all Mosel types and arbitrary data structures. This generic implementation obviously makes it possible for users to define their own union type basicvalue (limited to the five scalar types of xreflect) with access routines matching closely the restricted functionality available through xreflect:
uses "mmreflect"
! Defining a union type 'basicvalue' to hold scalars of basic Mosel types or 'text'
public declarations
basicvalue = string or integer or real or boolean or text
bvtrue, bvpi, bvhello: basicvalue
end-declarations
! Defining xreflect-style access routines
function getboolvalue(u: basicvalue):boolean
returned:=u.boolean
end-function
public function gettype(u: basicvalue):string
case u.typeid of
boolean.id: returned:="boolean"
integer.id: returned:="integer"
real.id: returned:="real"
string.id: returned:="string"
text.id: returned:="string"
else returned:="unsupported type"
end-case
end-function
bvtrue := true ! Same as: bvtrue := basicvalue(true)
bvpi := 3.14 ! Same as: bvpi := basicvalue(3.14)
bvhello := 'hello' ! Same as: bvhello := basicvalue('hello')
writeln("***Compatibility routines:")
writeln('bv value=', bvtrue.boolvalue) ! Output: bv value=true
writeln('bv type=', bvtrue.type) ! Output: bv type=boolean
However, unless such restrictive typing is indeed required we strongly recommend to switch to working with the generic union type any as shown in the following examples, using standard Mosel functionality and the new set of access routines provided through mmreflect.
The following Mosel code example shows correspondence of standard union type handling for
- type xreflect∼basicvalue
- subroutines xreflect∼get[bool|int|real|string|text]value and xreflect∼gettype
| xreflect | mmreflect |
|---|---|
!*** Working with type basicvalue
public declarations
bvtrue, bvseven, bvpi, bvhello, bvname: basicvalue
end-declarations
bvtrue := basicvalue(true)
bvseven := basicvalue(7)
bvpi := basicvalue(3.14)
bvhello := basicvalue('hello')
bvname := basicvalue(text('my name'))
writeln('boolvalue=', bvtrue.boolvalue)
! Output: boolvalue=true
writeln('is boolean:', bvtrue.type=XREFLECT_TYP_BOOL)
! Output: is boolean:true
writeln('intvalue=', bvseven.intvalue)
! Output: intvalue=7
writeln('is integer:', bvseven.type=XREFLECT_TYP_INT)
! Output: is integer:true
writeln('realvalue=', bvpi.realvalue)
! Output: realvalue=3.14
writeln('is real:', bvpi.type=XREFLECT_TYP_REAL)
! Output: is real:true
writeln('stringvalue=' ,bvhello.stringvalue)
! Output: stringvalue=hello
writeln('is string:', bvhello.type=XREFLECT_TYP_STRING)
! Output: is string:true
writeln('textvalue=', bvname.textvalue)
! Output: textvalue=my name
writeln('is string:', bvname.type=XREFLECT_TYP_STRING)
! Output: is string:true |
!*** Working with union types
public declarations
bvtrue, bvseven, bvpi, bvhello, bvname: any
end-declarations
bvtrue := true
bvseven := 7
bvpi := 3.14
bvhello := 'hello'
bvname := text('my name')
writeln('boolvalue=', bvtrue.boolean)
! Output: boolvalue=true
writeln('is boolean:', bvtrue.typeid=boolean.id)
! Output: is boolean:true
writeln('intvalue=', bvseven.integer)
! Output: intvalue=7
writeln('is integer:', bvseven is integer)
! Output: is integer:true
writeln('realvalue=', bvpi.real)
! Output: realvalue=3.14
writeln('is real:', bvpi is real)
! Output: is real:true
writeln('stringvalue=', bvhello.string)
! Output: stringvalue=hello
writeln('is string:', bvhello is string)
! Output: is string:true
writeln('textvalue=', bvname.text)
! Output: textvalue=my name
writeln('is text:', bvname is text) ! is text:true
writeln('is string:', bvname is string) ! is string:false |
Accessing scalars, retrieving type and structural information
The subroutines of xreflect search for model entities by their name. With mmreflect the entities are first retrieved into a union via a call to findident and all subsequent operations are carried out directly on this union.
The following Mosel code example shows mmreflect correspondence for
- subroutines xreflect∼getscalarvalue, xreflect∼setscalarvalue, xreflect∼getvaluetype, xreflect∼getstructtype, and xreflect∼getindexsettypes
| xreflect | mmreflect |
|---|---|
public declarations
mystr: string
myarr: array(range) of real
myset: set of integer
mylst: list of integer
mydate: date
mybool=true
myrng=1..5
end-declarations
!*** Retrieving and setting scalar values
mystr := 'hello'
writeln('mystr=',getscalarvalue('mystr'))
! Output: myvar=hello
setscalarvalue('mystr',basicvalue('world'))
writeln('mystr=',mystr) ! Output: myvar=world
!*** Accessing structural information
writeln('myvar=', getvaluetype('mystr'))
! Output: mystr=string
writeln('mystr struct is variable:',
getstructtype('mystr')=XREFLECT_STR_REF)
! Output: mystr struct is variable:true
writeln('myarr=', getvaluetype('myarr'))
! Output: myarr=real
writeln('myarr struct is array:',
getstructtype('myvar')=XREFLECT_STR_REF)
! Output: mystr struct is variable:true
writeln('myset=', getvaluetype('myset'))
! Output: myset=integer
writeln('myset struct is set:',
getstructtype('myset')=XREFLECT_STR_SET)
! Output: mystr struct is variable:true
writeln('myrng=', getvaluetype('myrng'))
! Output: myrng=integer
writeln('myrng struct is set:',
getstructtype('myrng')=XREFLECT_STR_SET)
! Output: mystr struct is variable:true
writeln('mydate=', getvaluetype('mydate'))
! Output: mydate=unsupported
writeln('mydate struct is variable:',
getstructtype('mydate')=XREFLECT_STR_REF)
! Output: mydate struct is variable:true
writeln('mybool=',getvaluetype('mybool'))
! Output: mybool=boolean
writeln('mybool struct is const:',
getstructtype('mybool')=XREFLECT_STR_CONST)
! Output: mystr struct is variable:true
writeln('mylst=', getvaluetype('mylst'))
! Output: mylst=integer
writeln('mylst struct is unsupported:',
getstructtype('mylst')=XREFLECT_STR_UNSUPPORTED)
!*** Index set type information
public declarations
myarr2: array(set of integer,set of string) of real
end-declarations
writeln('index set types=',
getindexsettypes('myarr2'))
! Output: index set types=[`integer',`string']
|
public declarations
mystr: string
myarr: array(range) of real
myset: set of integer
mylst: list of integer
mydate: date
mybool=true
myrng=1..5
a: any
end-declarations
!*** Retrieving and assigning scalar values
mystr := 'hello'
asproc(findident('mystr', a))
writeln('mystr=',a) ! Output: mystr=hello
a := 'world'
writeln('mystr=',mystr) ! Output: mystr=world
!*** Accessing structural information
res:=findident('mystr', a)
writeln(testtype(res,STRUCT_REF+string.id)) ! Output: true
writeln('mystr=string: ', a is string)
! Output: mystr=string: true
writeln('mystr struct is variable:', a.struct=STRUCT_REF)
! Output: mystr struct is variable:true
asproc(findident('myarr', a))
writeln('myarr=real: ', a.eltype=real.id)
! Output: myarr=real: true
writeln('myarr struct is array:', a.struct=STRUCT_ARRAY)
! Output: myarr struct is array:true
asproc(findident('myset', a))
writeln('myset=integer: ', a.eltype=integer.id)
! Output: myset=integer: true
writeln('myset struct is set:', a.struct=STRUCT_SET)
! Output: myset struct is set:true
asproc(findident('myrng', a))
writeln('myrng=integer: ', a.eltype=integer.id)
! Output: myrng=integer: true
writeln('myrng struct is set:', a.struct=STRUCT_SET)
! Output: myrng struct is set:true
asproc(findident('mydate', a))
writeln('mydate=date: ', a.typeid=date.id)
! Output: mydate=date: true
writeln('mydate struct is variable:', a.struct=STRUCT_REF)
! Output: mydate struct is variable:true
asproc(findident('mybool', a))
writeln('mybool=boolean: ', a.eltype=boolean.id)
! Output: mybool=boolean: true
writeln('mybool struct is const:', a.struct=STRUCT_CONST)
! Output: mybool struct is const:true
asproc(findident('mylst', a))
writeln('mylst=integer: ', a.eltype=integer.id)
! Output: mylst=integer: true
writeln('mylst struct is list:', a.struct=STRUCT_LIST)
! Output: mylst struct is list:true
!*** Index set type information
public declarations
myarr2: array(set of integer,set of string) of real
lst: list of integer
end-declarations
asproc(findident('myarr2', a))
forall(i in 1..a.array.nbdim) lst+=[a.array.index(i).eltype]
writeln('index set types=',lst)
! Output: index set types=[1,3] |
Accessing sets
Since the set access routines in mmreflect work on unions, the type of the set must be specified when accessing the corresponding set.
The following Mosel code example shows mmreflect correspondence for
- subroutines xreflect∼addsetelement, xreflect∼finaliseset, xreflect∼checksetcontains, xreflect∼getsetelements, and xreflect∼copysetelements
| xreflect | mmreflect |
|---|---|
public declarations
dlst: list of basicvalue
end-declarations
myset := {1,3}
addsetelement('myset', basicvalue(4))
writeln('myset=', myset) ! Output: myset={1,3,4}
finaliseset('myset') ! No further changes
!addsetelement('myset',basicvalue(6)) ! Error
writeln('contains 6=', checksetcontains('myset',
basicvalue(6))) ! Output: contains 6=false
writeln('myset=', getsetelements('myset'))
! Output: myset=[1,3,4]
dlst:=[]
copysetelements('myset', dlst)
writeln(dlst) ! Output: [1,3,4]
|
public declarations dlst: list of any mysettype=set of integer end-declarations myset := {1,3} asproc(findident('myset', a)) if a is not mysettype then ! Alternatively: !if findident('myset', a, mysettype.id)=0 then writeln("Unexpected type"); exit(1) end-if a.mysettype+={4} writeln('myset=', myset) ! Output: myset={1,3,4} finalise(a.set) ! No further changes !a+={6} ! Results in an error writeln('contains 6=', 6 in a.mysettype) ! Output: contains 6=false writeln('myset=', a) ! Output: myset={1,3,4} dlst:=[] dlst:=list(a.set) writeln(dlst) ! Output: [1,3,4] |
Accessing arrays
When accessing arrays via mmreflect functionality the type of array elements needs to be stated, with the exception of the routines delcell, exists, and create for which it is sufficient to state the generic type any.
The following Mosel code example shows mmreflect correspondence for
- Subroutines xreflect∼arrayentryexists, xreflect∼getarrayentry, xreflect∼setarrayentry, xreflect∼getindexsetelements, xreflect∼copyindexsetelements, xreflect∼delarray, and xreflect∼delarrayentry
| xreflect | mmreflect |
|---|---|
public declarations
myarr4: dynamic array(range,set of integer) of real
dlst: list of basicvalue
end-declarations
myarr4(1,100) := 5.0
myarr4(1,101) := 5.1
myarr4(2,101) := 5.2
writeln('exists(2,100)=', arrayentryexists('myarr4',
[basicvalue(2),basicvalue(100)]))
! Output: exists(2,100)=false
!*** Accessing array elements
writeln('myarr4(2,101)=', getarrayentry('myarr4',
[basicvalue(2),basicvalue(101)]))
! Output: myarr4(2,101)=5.2
setarrayentry( 'myarr4', [basicvalue(1),
basicvalue(101)], basicvalue(17.5) )
writeln('myarr4(1,101)=', myarr4(1,101))
! Output: myarr4(1,101)=17.5
setarrayentry( 'myarr4', [basicvalue(3),
basicvalue(100)], basicvalue(2.0) )
writeln('myarr4_i1=', getindexsetelements('myarr4',1))
! Output: myarr4_i1=[1,2,3]
copyindexsetelements('myarr4',1,dlst)
writeln(dlst) ! Output: [1,2,3]
delarrayentry('myarr4',
[basicvalue(1),basicvalue(101)])
writeln('exists(1,101)=', arrayentryexists('myarr4',
[basicvalue(1),basicvalue(101)]))
! Output: exists(1,101)=false
delarray('myarr4')
writeln('size=', myarr4.size)
! Output: size=0
|
public declarations
myarr4: dynamic array(range,set of integer) of real
dlst: list of any
end-declarations
myarr4(1,100) := 5.0
myarr4(1,101) := 5.1
myarr4(2,101) := 5.2
stat:= findident('myarr4', a)
if not testtype(stat, STRUCT_ARRAY) then exit(1); end-if
writeln('exists(2,100)=', exists(a.array(2,100).any))
! Output: exists(2,100)=false
!*** Array element access using standard union handling
writeln('myarr4(2,101)=', a.array(2,101).real)
! Output: myarr4(2,101)=5.2
a.array(1,101).real := 17.5
writeln('myarr4(1,101)=', myarr4(1,101))
! Output: myarr4(1,101)=17.5
!*** Alternative forms using array element access routines
setarrval(a, 7.5, 1,101)
getarrval(myarr4, u, 1,101)
writeln('myarr4(1,101)=', u) ! Output: myarr4(1,101)=7.5
setarrval(myarr4, 2.5, [1,101])
getarrval(a, u, [1,101])
writeln('myarr4(1,101)=', u) ! Output: myarr4(1,101)=2.5
a.array(3,100).real := 2.0
writeln('myarr4_i1=', a.array.index(1))
! Output: myarr4_i1=1..3
dlst:= list(a.array.index(1))
writeln(dlst) ! Output: [1,2,3]
delcell(a.array(1,101).any)
writeln('exists(1,101)=', exists(a.array(1,101).real))
! Output: exists(1,101)=false
reset(a.array) ! Same as: delcell(a.array)
writeln('size=', myarr4.size)
! Output: size=0 |
Array iterators
The module mmreflect defines the type iterator that can be used in a similar way as the type arrayiterator of xreflect for enumerating the entries defined for a Mosel array.
The following Mosel code example shows mmreflect correspondence for
- type xreflect∼arrayiterator
- subroutines xreflect∼gethasvalue, xreflect∼getindices, xreflect∼getvalue, xreflect∼iteratorinit, and xreflect∼nextvalue
| xreflect | mmreflect |
|---|---|
public declarations myarray:dynamic array(range,set of string) of real end-declarations ! Populate our example data-set myarray(100,'fred') := 100.1 myarray(100,'jim') := 101.5 myarray(101,'fred') := 215.7 ! Iterate through array entries using the arrayiterator declarations it:arrayiterator end-declarations iteratorinit(it, 'myarray') writeln(it.hasvalue) ! Output: false (before start) while (nextvalue(it)) do write('myarray(', it.indices) ! Index tuple: list of basicvalue writeln(') = ', it.value) end-do ! Output: ! myarray([100,fred]) = 100.1 ! myarray([100,jim]) = 101.5 ! myarray([101,fred]) = 215.7 writeln(it.hasvalue) ! Output: false (after end) |
public declarations myarray:dynamic array(range,set of string) of real end-declarations ! Populate our example data-set myarray(100,'fred') := 100.1 myarray(100,'jim') := 101.5 myarray(101,'fred') := 215.7 ! Iterate through array entries using the iterator declarations it:iterator u:any end-declarations inititer(it, myarray) writeln(it.status) ! Output: 0 (before start) writeln(exists(myarray(it))) ! Output: false while (nextcell(it)) do write('myarray(', it.indices) ! Index tuple: list of any writeln(') = ', myarray(it)) !*** Alternative form: using getarrval with iterator ! getarrval(myarray,u,it.indices) ! write(') = ',u) end-do ! Output: ! myarray([100,fred]) = 100.1 ! myarray([100,jim]) = 101.5 ! myarray([101,fred]) = 215.7 writeln(it.status) ! Output: 2 (after end) writeln(exists(myarray(it))) ! Output: false |
Accessing subroutines
The module mmreflect generalizes the handling of subroutines to include subroutine arguments and it also adds functionality for handling functions.
The following Mosel code example shows mmreflect correspondence for
- subroutines xreflect∼findproc and xreflect∼callproc
| xreflect | mmreflect |
|---|---|
!*** Calling a procedure
public procedure myproc
writeln('hello world');
end-procedure
callproc('myproc') ! Output: hello world
public procedure myproc1
writeln('hello');
end-procedure
public procedure myproc2(xyz:string)
writeln('world: ', xyz);
end-procedure
! Subroutines with arguments are not supported
!*** Checking for a subroutine
writeln('findproc(myproc1)=', findproc('myproc1'))
! Output: findproc(myproc1)=true
! Calling the subroutine
callproc('myproc') ! Output: hello world
writeln('findproc(myproc2)=', findproc('myproc2'))
! myproc2 will not be found as it takes an argument
! Output: findproc(myproc2)=false
!*** Functions are not supported
public function myfunc: text
returned:=text('-')*10
end-function
writeln('findproc(myfunc)=', findproc('myfunc'))
! Output: findproc(myfunc)=false |
!*** Calling a procedure
public procedure myproc
writeln('hello world');
end-procedure
callproc('myproc') ! Output: hello world
public procedure myproc1
writeln('hello');
end-procedure
public procedure myproc2(xyz:string)
writeln('world: ', xyz);
end-procedure
! Calling a subroutine with an argument
callproc('myproc2', 'my text') ! Output: world: my text
!*** Checking for a subroutine
declarations
srtype=procedure ! Type definition for 'findident'
srtype2=procedure(string)
end-declarations
writeln('findproc(myproc1)=',
getstruct(findident('myproc1',a,srtype.id))=STRUCT_ROUTINE)
! Output: findproc(myproc1)=true
! Calling the subroutine that has been retrieved
callproc(a) ! Output: hello world
writeln('findproc(myproc2)=',
getstruct(findident('myproc2',a,srtype.id))=STRUCT_ROUTINE)
! Output: findproc(myproc2)=false
writeln('findproc(myproc2)=',
getstruct(findident('myproc2',a,srtype2.id))=STRUCT_ROUTINE)
! Output: findproc(myproc2)=true
!*** Support for functions
public function myfunc: text
returned:='-'*10
end-function
writeln('findproc(myfunc)=',
testtype(findident('myfunc',a), STRUCT_ROUTINE+text.id))
! Output: findproc(myfunc)=true
declarations
res: any
end-declarations
callfunc(a,res)
writeln("Result=", res) ! Output: Result=---------- |
© 2001-2023 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.
