Sage-Code Laboratory
index<--

EVE Data Processing

EVE language is all about data processing. By using collections and control structures one can load, validate, modify and store data. In this article we review some of the concepts we already know to create useful design patterns for data processing.

Bookmarks:

Processes

A process is a set of tasks that can pass or fail depending on conditions. Any driver, aspect or routine can implement processes. A process can be divided into tasks. All tasks of a single process are execute sequential from top downs. When the last task is finished the process is ending.

Keywords:

processcreate one process (driver/aspect/routine)
task create one step in the process
try begin task executable region
pass end current task with result "pass"
fail end current task with result "fail"
skip continue to next task
skip tocontinue to specified tasks
retry redo the task that raise a recoverable error
over stop process execution and release resources
abort ignore all next tasks and execute the release
raise create error or propagate the error

Main Process

A driver or aspect can have a single main process. This can be divided into tasks. Each task can resolve one small use-case. Tasks are executed in serial mode. No matter if a task "pass" or "fail", the process continue until the end if not intrerupted by using an intreruption statement.

Pattern:

# define process with tasks
process
    ** preconditions
    exit if condition;    
    ....
    ** open resources
    ...
    task c1:"description" try
        ...
        skip if condition;  
    task c2:"description" try
        ...
        over if condition;          
    task c3:"description" try
        ...
        pass if condition;
    task c4:"description" try
        ...
        fail if condition;
recover  
    ** exception region
    ...
    retry if condition;    
    ...
    raise if condition;
release
    ** close resources
    ...    
report
    ** report the errors
    ...    
return;

Inreruptions

Intreruption keywords (exit, halt, over) can be used to intrerupt a process but is not the normal way to terminate a process. These keywords are used for processes that are not divided into tasks. Using these keywords, a process is intrerupted but the finalization regions are not executed.

List operations

We can add elements to a list or remove elements from the list using next operations:

List concatenation

List concatenation is ready using operator “++”. This operator represent union. Therefore List union act very similar to append, except we add multiple elements.

#list demo
driver list_concat:

locals
  List[Symbol] a = ['a','b','c']; //  initialized
  List[Symbol] b = ['1','2','3']; //  initialized
  List[Symbol] c; //  deferred initialization
process
  store c := a ++ b;
  print c; //  ['a','b','c','1','2','3'];
return;

Join() built-in

The join function receive a list and convert elements into a string separated be specified character.

#list join() demo
driver list_join:

locals
  String str; //  Null String
process
  store str := join([1,2,3],",");
  print str; // "1,2,3"
return;

Split built-in The join function receive a list and convert elements into a string separated be specified character.

**list split demo
driver list_split:

locals
  List[Integer] lst; //  Null List
process
  ** initialize new reference for "lst"
  lst := split("1,2,3",","); 
  print lst; // (1,2,3)
return;

List as queue

Two operations are possible

List as stack

Two operations are possible

Note: There is no protection about using a List as stack or queue.

Other built-ins

Following other functions should be available

Special attributes A list has properties that can be used in logical expressions:

List.empty();  // true or false
List.full();   // true or false

Collection iteration

A special while loop that is executed for each element belonging to a collection.

Pattern:

#iteration
locals
    ClassName element := collection.first();
process  
    while element is not null loop
       ** statements
       ...
       element := collection.next(element);
       ...
       write element;
    end loop;   
    print;
return;

The "element" is local to iteration and is used as control variable.

Example:

# list iteration
driver list_iteration:

locals
  List[Symbol] my_list; //  this list is Null
  String e;  
process  
  my_list := ['a','b','c','d','e'];
  for e in my_list loop
    write e;
    if e == 'd' then
      break; //  early termination;
    else
      write(',');
    end if;
  end loop;
  print; // c,d
return;

Using map table

Maps are sorted in memory by key for faster search. It is more difficult to search by value because is not unique and not sorted. To search by value one must create a loop and verify every element. This is called full scan and is very slow so you should never use this routine.

Map Initialization

Initialize a collection later than declaration.

# local map initialization
driver map_init:

locals
  Map my_map; //uninitialized collection
process
  ** initialize my_map with values
  my_map := {(1:'a'),(2:'b'),(3:'c')};
  
  ** check if a key is present in a map collection
  expect 3 in my_map; // pass
return;  

Create Elements

** create new elements
driver map_append:
  Map(String, String): animals = {}; //empty collection
process
  ** create new element pairs
  animals += ('Bear':'dog'); 
  animals += ('Kiwi':'bird');

  ** verify effect of append  
  print  animals; 
return;

Output:

{('Bear':'dog'),('Kiwi':'bird')}

Modify Elements

#update a map
driver map_update:

locals
  Map animals = {("dogs":0),("birds":0)}; 
process
  ** print the new collection
  print  animals;
  
  ** modify the collection
  animals['dogs']  := 1;
  animals['birds'] := 2;
  animals['birds'] += 3;  

  ** print the new collection
  print  animals;
return;

Output:

{("dogs":0),("birds":0)};
{("dogs":1),("birds":5)}; 

Iteration of Map items

Collections have common methods that enable traversal using for loop.

{List, Map, Set}

built-in:

set iteration Map and Set are similar. We can visit all elements using for loop:

Example:

# map iteration
driver map_iteration:

locals
  Map my_map := {("a":1),("b":2),("c":3)};
  Symbol key;
  Integer value;  
process  
  for (key: value) in my_map loop
    ** print pairs (key:value)
    print "(#s:#n)" ? (key, value);
  end loop;
return;

Will print:

("a",1)
("b",2)
("c",3)

String: concatenation

Strings can be concatenated using:

Example:

** example of string concatenation
driver string_concat:

locals
  String str = "";  //empty String
process
  ** set string value using different operators
  str := "this " + " string"; expect str == "this  string";
  str := "this " - " string"; expect str == "this string";  
  str := "this/" / " string"; expect str == "this/string";  
  str := "this"  .   string ; expect str == "this/string";  
return;

path concatenation

Two strings can be concatenated using concatenation operator "/" or "\". This operator is used to concatenate "path" strings or URL locations. Notice "\" is also escape character used for string templates.

# path concatenation
locals
  String s = ""; //empty string
process
  s := 'te/' / '/st'; //  "te/st" Linux
  s := 'te/' \ '/st'; //  "te\st" Windows
return;

Text functions

Note: The text also support escape sequences like a normal string. In a text literal we do not have to escape the single quote symbols: "'". However we have to escape the double quotes like: "This is "quoted" text". This is very rare since quoted text should use symbols: "« »" like "«quoted»"


Read next: Databases