Project

General

Profile

Actions

Types in Scol

The most used Scol types are :

I : integer
S : string
F : float
Chn : SCOL channel
Srv : SCOL server
Env : SCOL environment
Comm : communication (typically, between VMs)
[u0 u1] : Tuples where u0, u1 are Scol types
[u0 rn] : List where u0 is a Scol type, rn is the level of recursivity (r1, in the mostly cases)
tab u0 : Array

All these types are availables from the minimal environment.

However, you can create yourself a type for your application. It will be available only from your application (unless you share it in a library by example).

For that, you are two different ways : struct or typedef. Their uses are differents, of course.

struct

struct creates a structure like the C-structure (almost ...). A structure is a type with several fields. A name and a Scol type define each field. In fact, each field is an internal and opaque function.
The first letter of the structure name must be an uppercase letter. There is no constraint for the fields.

struct <Name_of_structure> = [<name_field_1> <type1>, <name_field_2> <type2>, ..., <name_field_N> <typeN>]] mk<Name_of_structure>;;

Like typeof or var, the declaration ends by a double semicolon.
All names are choosen by you, at your convenience, except struct, of course.
mk<Name_of_structure> is the constructor for your structure. It is also a function (fun [<type1> <type2> ... <typeN>] <Name_of_structure>). You must initialize (build) your structure after its declaration and before its use !

Example :

// Declaration
struct MYDATA = [ MD_sName : S, MD_iValue : I ] mkMYDATA;;

// Initialization (build)
fun initData (name, value)=
      mkMYDATA [name value]
;;

// Get a value (here, the field 'name')
fun getDataName (mydatastr)=
      mydatastr.MD_sName
;;

// Set a value
fun setDataName (mydatastr, newname)=
    set mydatastr.MD_sName = newname
;;

fun main ()=
    // first, you initialize the structure !
      let initData "Bob" 1 -> mydatastr in
    (
    // you display a value
    _fooS strcat ">>> name : " (getDataName mydatastr);
    // you change a field
    setDataName mydatastr "Alice";
    // you display a value
    _fooS strcat ">>> name : " (getDataName mydatastr);
     0
     );
;;

This allows to create an encapsulated object, opaque or not. Another example can be found in A console in Scol, with a mini-api around a structure. Structures are common objects in Scol.

typedef

The use is more complex.
It allows to have several possible types for a same variable or any other valid object. This is an equivalent at the C-union. This is normally forbidden in Scol (the type of a variable is strong, fixed and not modifiable).
For each different type inside the new type, an internal and opaque function, named constructor, translates the value object.

To define it :

typedef <new_type> = <constructor_1> <type_1> | <constructor_2> <type_2> | ... | <constructor_N> <type_N> | <constructor_default> ;;

<constructor_X> is a function, its type is fun [ <type_X> ] <new_type>

The names of a constructor and of a new type are free.
<type_X> must be a known type in the current environment : either a Scol type or any customized type (via struct or typedef) declared previously.

The last constructor has never a <type_X>. This is the default constructor; it is used if no match with other constructors.

Example :

/* New scol type named 'NewType'. It can set by a "subtype" (in fact in function) NTI, NTF, ... */
typedef NewType =    
NTI I
| NTF F
| NTS S
| NTn;;

For you, if the value is an integer, NTI will be asked. If it is an float, it will be NTF, a string with NTS, otherwise by NTn.

After be defined, you can use it !
A such object is processed using the match function :

fun anyFunction ()=
    match <variable> with
    (<constructor_1> <local_variable_1> -> instruction)
    | (<constructor_2> <local_variable_2> -> instruction)
    ...
    | (<constructor_default> -> instruction);
    0;;

You can write less of constructors than defined in the type declaration. Others cases will be considered by the default constructor.

| (<constructor_default> -> instruction);
is the same thing that | (_ -> instruction);

So, we get :

typedef NewType =    
NTI I
| NTF F
| NTS S
| NTn;;

typeof X = NewType;;    /* global ariable NewType */

fun myFunction ()=
    match X with
    (NTI e -> (_fooS "X is an integer"; 0))
    | (NTF e -> (_fooS "X is a float"; 0))
    | (NTS e -> (_fooS "X is a string"; 0))
    | (_ -> (_fooS "X is another thing"; 0));;

fun main ()=
    _showconsole;

    set X = NTI 10;
    myFunction;
    set X = NTF 5.0;
    myFunction;
    set X = NTS "Scol is a free language";
    myFunction;

    0;;

License : CC-BY-SA-2.0
Tutorial by iri
Updated by /

Updated by lpousse almost 7 years ago · 3 revisions