Sage-Code Laboratory
index<--

Bee Data Types

Data types represent abstract domains of values. In other words, data type represent constrain rules that can be used to validate a particular data value. Data"type" is an attribute of any data element. In Bee there is no data element without this attribute.

Bee use 2 kind of data types:

  1. Primitive data types;
  2. Composite data types;

Usability:

Primitive Types

Primitive data types are defined using one capital letter.

Alias Code Description + Default representation
Logic L Numeric enumeration of two values: 0 = False, 1 = True
Alpha A Alpha-numeric code point E-ASCII ('0'..'9') ('a'..'Z')
Binary B Binary number on 8 bit, max: 0b11111111 (0..255) (0..0xFF)
Unicode U Unsigned code point on 32 bit, max: U-FFFFFFFF (UTF32)
Rational Q Fix point representation number: like 1/2. Notation: Q(14,17)
Natural N Unsigned large positive integer 64 bit [0..+]
Integer Z Signed large integer 64 bit [-..+] Z(64)
Real R Double precision float 64 bit (-..+) R(64)

Notes:

Constant Literals

These are symbolic representations for primitive data types:

Example Type Literal characters
'a' A (+-) & (0..9) & (a..z) & (A..Z)
'Ω' U (Δ Λ Φ Γ Ψ Ω Σ Π π ⊥ ǁ α β ɣ ε δ μ ω ...)
"str" S (∀ UTF8)
0b11111111 B (0b) & (0,1)
1234567890 N (0,1,2,3,4,5,6,7,8,9)
+0 Z (-+) & (0,1,2,3,4,5,6,7,8,9)
0xFFFF A (0x) & (0,1,2,3,4,5,6,7,8,9) & ABCDEF
U+FFFF U (U+) & (0,1,2,3,4,5,6,7,8,9) & ABCDEF
U-FFFFFFFF U (U-) & (0,1,2,3,4,5,6,7,8,9) & ABCDEF
0.05 R (-.) & (0,1,2,3,4,5,6,7,8,9)
-1/2 Q (-/) & (0,1,2,3,4,5,6,7,8,9)
1E10 R (-1E)& (0,1,2,3,4,5,6,7,8,9)
1e10 R (-1e)& (0,1,2,3,4,5,6,7,8,9)

note

Composite types

Predefined composite types have an alias starting with capital letter:

Alias Type Description
Complex C Double precision pair of double float numbers (9r+9j)
String S UTF8 encoded double quoted string "α β ɣ ε δ μ ω"
Text X Multi-line large block of text ...
Date D "DD/MM/YYYY"
Time T "hh:mm,ms"
Error E Error object: {code, message, line}
File F File handler

Notes:

Collection types

Bee define a collection literal using a special notation based on brackets.

delimiter collection types
() List
[] Array / Matrix
{} Ordinal / Set / Hash / Object

Notes:

Type declaration

User can define super-types and sub-types using operators ":" and "<:".

** declare new type
type Type_Identifier: type_descriptor <: super_type;
** declare variables using new type
make var_name,var_name ... ∈ Type_Identifier;

Notes:

Range

A range is a notation that designate a sub-set of consecutive integer numbers between two limits: lower limit and upper limit included in round paranthesis and separated by two dots (..) or (!).

Syntax:

Range ::= (min..max);
Range ::= (min.!max); //exclude upper limit
Range ::= (min!.max); //exclude lower limit

Notes:

Example:

#integer domain
rule main():
  print (0..5); // 0,1,2,3,4,5
  print (0.!5); // 0,1,2,3,4
  print (0!.5); // 1,2,3,4,5
  
  pass if  32667 ∈ (0..+); //expect to pass
  pass if -32668 ∈ (-..0); //expect to pass
return;

Ranges can use symbols that are ASCII or Unicode. In this case the symbols must be included in single quotes: 'X' or use U+ notation:

Example:

** sub-type declarations
type Digit:    ('0'..'9')       <: Z;      
type Capital:  ('A'..'Z')       <: A;  
type Lowercase:('a'..'z')       <: A;  
type Latin:    (U+0041..U+FB02) <: U;
rule main():
  ** following statements should pass
  pass if '0' ∈ Digit;     
  fail if 'x' ∈ Capital; 
  pass if 'X' ∈ Capital; 
  pass if 'e' ∈ Latin;   
return;  

Domains

Domain is very symilar to range except a domain has a ratio. This is the difference, the numbers are not integers, can be fractionar or Q umber.

Domain ::= (min..max:ratio)  <: Super_Type

Examples:

** generate rational numbers
print (0..1:1/4); // 0/4, 1/4, 2/4, 3/4, 4/4

** generate float numbers
print (0..1:0.25); // 0.00, 0.25, 0.50, 0.75, 1.00

Constant declaration

Constants are defined identifiers for literal constants.

** using explicit type
stow constant_name: constant_literal ∈ type_name; 

** using implicit type
stow constant_name:= constant_literal;  

Notes:

Example:

#symbol constants
stow n: U+2200     ∈ A; //Symbol: ∀
stow n: U-00002200 ∈ U; //Symbol: ∀

Note:

Variable declarations

Variables are defined using keyword make plus one of the operators:

operator purpose
declare variable/element type
: define type | set initial value | pair up operator
:= type inference | share a reference | assign operator
:: deep copy | duplicate object | cloning operator

Notes:

** primitive variable declarations with type
make var_name ∈  type_name; // declaration only type without initial value
make var_name: value ∈  type_name; // declaration with initial value and type

** Variable declaration using type inference
make var_name := expression; //expression ":=" do not require type hint ("∈").

** Multiple variables can be define in one single line using comma separator:
make var1, var2 ... ∈  TypeName;   //default initial values
make var1, var2 ... := Expression; //use type inference for all initial values

** Initialize multiple variables, of the same type (type is required)
make var1:con1, var2:con2 ... ∈ TypeName; 

Modify values

One can modify variables using alter statement.

Example:

#fragment of code

make a:10, b:0 ∈ Z; // initialize two variables
alter b := a + 1;   // modify b using binding operator :=
alter b += 1;       // modify b using modifier +=
print b;            // expected 12

Notes:

Examples:

** declare a constant
stow pi: 3.14 ∈ R;
** declare multiple variables
make a   ∈ Z; //Integer 
make x,y ∈ R; //Double
make q,p ∈ L; //Logic
rule main():
  ** using modifiers
  alter a := 10; //modify value of a := 10
  alter a += 1;  //increment value of a := 11
  alter a -= 1;  //decrement value of a := 10
  
  ** modify two variables using one single constant
  alter x, y := 10.5;
  
  ** modify two variables using two constants
  alter q, p := True, False;  
  
  ** swapping two variables
  alter p, q := q, p;
return;  

Type conversion

When data type mismatch you must perform explicit conversion.

Example:

make a: 0, b:20 ∈ Z;
make v: 10.5, x: 0.0 ∈ R;
rule main():
** explicit conversion
   alter a := v :> N;
   print a; //truncated to 10 
** explicit conversion
   alter x := b :> R;
   print x; //expect 20.00
return;   

Notes:

Alphanumeric type

Bee define A as single UTF-8 code point with representation: U+HH

make a, b ∈ A; //ASCII 
make x, y ∈ B; //Binary integer
rule main():
  alter a :='0';     //ASCII symbol '0'
  alter x := a :> B; //convert to binary 30
  alter y := 30;     //decimal code for '0'
  alter b := y :> A; //convert to ASCII symbol '0'
return;  

Type inference

You can use symbol ":=" to initialize variables using type inference.

** declare constants
stow a := 4;   //integer constant
stow b := 2.5; //real constant
stow c := 1/8; //rational constant
** declare variables
make x := 0;   //integer variable 
make y := 0.0; //real variable 
make z := 0/0; //rational variable

Type checking

We can use variable type to validate expression type.

** using type inference
make a := 0;   //integer variable 
make b := 0.0; //real variable 
rule main():
  alter a:= 10.5; //Warning: a is of type: Integer  
  alter b:= 10;   //Warning: b is of type: Real
  print a, b;     // 10, 10.00
return;  

You can use operator "∈" to verify data type:

make a := 0 ∈ Z;
rule main():
  ** expected: Integer
  fail if ¬ (a ∈ Z); // fail if a is not integer
return;  

Logic type

Logic type is an enumeration of two public symbols: False and True

type .L: {.False: 0, .True: 1} <: Ordinal;
** printing logical values
rule main():
  print True;  //1
  print False; //0
return;  

Logic operations

Bee uses several familiar logic operators from mathematics:

Precedence: { ¬, ∧, ∨, ⊕, = }. Symbol ¬ apply first (has higher precedence)

bitwise

In Bee we define special operators to perform bitwise operations. One opperator is overwrite: ⊕. This operator (xor) can operate on both, logical values or expressions and also on integer numbers.

# betweese opperations
print 4 | 3;//out:7 is becouse 100 ∨ 011 = 111 = 7;
print ~4    //out:3 is becouse: 100 ⊕  100 = 011 = 3;
print 4 & 7 //out:4 is becouse: 100 ∧ 111 = 100 = 4;
print 4⊕4  //out:0 is becouse: 100 ⊕ 100 = 000 = 0;
print 1<<2  //out:2 is becouse: 001 << 2   = 100 = 4;
print 6<<2  //out:1 is becouse: 110 << 2   = 001 = 1;

comparison Comparison operators will create a logical response: 1 = True or 0 = False

Example:

make  (x, y):4 ∈  Z; //primitive integer
rule main():
  ** value comparison
  print x = 4;  //1 (equal)
  print x ≡ 4;  //1 (identical)
  print x = y;  //1  
  print x ≡ y;  //1 
  print x ≠ 5;  //1 (different)
  print x!≡ 5;  //1 (not identical)
  
  ** reference ordering
  print x ≥ y;  //1: x and a are actually equal
  print x ≥ 4;  //1: greater or equivalent to 4
  print x ≤ 4;  //1: less than or equivalent to 4
  print x > 4;  //0: not greater than 4
  print x < 4;  //0: not less than 4
  
  
  ** arithmetic expressions have primitive results
  print x - 4 = 0; //1 
  print x - 4 ≡ 0; //1 
return;  

singleton

Primitive types are unique. That means they are identical.

** primitive values are singleton
print  1  ≡  1;  //1
print `s` ≡ `s`; //1

Precedence:

Logic operators have greater precedence than comparison operators.

Logical expression

Logical expression have value { 0 = False, 1 = True }

make x := False ∈ L; 
make y := True  ∈ L; 
rule main():
  ** expressions with single operant
  print   x; //0
  print ¬ x; //1
  
  ** expressions with two operands
  print (x = y); //0
  print (x ≡ y); //0
  print (x ≠ y); //1
  print (x < y); //1
  print (x > y); //0
  print (x ∧ y); //0
  print (x ∨ y); //1
  print (x ⊕ y); //1
return;  

Notes:

coercion Any numeric expression can be converted to a logic value using coercion operator ":>" (easy to memorize if you think is like an arrow).

make (x, y) ∈ L;
make (a:0.0, b:1.5) ∈ R;
rule main():
  alter x := a :> L; //0
  alter y := b :> L; //1
return;  

Notes:

design

** logical values are singleton
print True  ≡ True;   //1
print False ≡ False;  //1
** logical values are numeric
print False - True; //-1 
print True  + True; //+2
** Null value is a singleton
print Null  ≡ Null   //1
** Null is not the same as false
print Null  ≡ False  //0
print Null  = False  //0

Conditionals

A conditional is a logic expression used to control statement execution.

statement if condition;

The statement is executed only if the expression evaluate to True.

restrictions:

  1. Can not use "if" with type statement;
  2. Can not use "if" with make statement;
  3. Can not use "if" with block statement;
make a := 0 ∈ Z;
rule main():
  ** conditional execution
  alter a := 1 if a = 0;
  ** conditional print
  print "a is 0" if a = 0;
return;  

Notes:

Pattern Matching

Instead of ternary operator we use conditional expressions. These expressions are separated by coma and enclosed in ().

Syntax:

make var ∈ type;
rule main():
  ** single condition matching
  alter var := (xp1 if cnd1, xp);
  
  
  ** multiple matching with default value
  alter var := (xp1 if cnd1, xp2 if cnd2,...xp);
  
  ** alternative code alignment
  alter var := 
    (xp1 if cnd1
    ,xp2 if cnd2
    ,xp);
return;  

Legend:

Example:

rule main():
   make x := '0'; //symbol
   write "x:"
   read   x;
   
   make kind := ("digit" if x ∈ ['0'..'9'], "letter" if x ∈ ['a'..'z'],or "unknown");
   print ("x is " + kind); //expect: "x is digit"
return;

Type inference

Type inference is a logical deduction of data type from constant literals.

Bookmarks:

Default

Each literal has associated a default type, induced by operators {":=", "::"}.

** string expressions
make c := 'a'     ;  //type = A
make s := '∈'     ;  //type = U
make s := "str"   ;  //type = S
make b := <Text>  ;  //type = Text
** numeric expressions
make i := 0;    //type = Z
make j := 0.50; //type = R
** define synonyms for logic constants
stow false := False; //type L = 0
stow true  := True;  //type L = 1
** multiple variables get same value
make x, y, z := 5; //type = Z for all
** multiple variables get multiple values
make int, rea := 4, 4.44;
print type(int); // Z
print type(rea); // R

Composite

Composite structures are using () [] and {} to create different data types. Next you can study some examples. We wi explain later all these types: List, Map, Array, Object, String. All of these are also called Bee collections.

** boxed integer (type = Z)
make i := [10]; //array of one value!
** list of one value (Z)
make a := (1,); 
** list of integers (Z)
make b := (1,2); 
** list of symbols (type = A)
make l := ('a','b');
** list of Unicode symbol (type = U)
make u := ('Δ', 'Λ', 'Γ');
** array with capacity of 4 integers: Z
make d := [1,2,3,4];
** array with capacity of 10 real numbers: R
make e := [0.00](10);
** data set of 4 integers: Z
make s := {1,2,3,4};
** hash map of (Z: String)
make c := {(1:"storage"),(2:"string")};
** object with two attributes: name ∈ String, age ∈ Z 
make b := {name:"Goliath", age:30};

Parameters

When we define parameters we can use type inference only for optional parameters:

Optional Parameters:

** in rule foo, parameters a, b are optional.
rule foo(a:= 0, b:= 0) => (r ∈ Z):
  alter r := a + b;
rule;  
        
rule main():        
  print foo();    // 0               
  print foo(1);   // 1
  print foo(1,2); // 3
return;  

Multiple parameters:

** parameters: a, b are mandatory, c is optional.
rule foo(a, b ∈ Z, c := 0) => (r ∈ Z):
  alter r := (a + b + c);
return;  
rule main():
  print foo(1,2);   // 3
  print foo(1,2,3); // 6
  print foo(1);     // Error: expected 2 arguments
return;  

Pass arguments by name:

We can use parameter name and pair-up ":" symbol for argument value.

** rule with optional parameters (Z)
rule bar(a := 0, b := 0, c := 0 ∈ Z) => (result ∈ Z):
  alter result := (a+b+c);
return;  
** observe we use pair-up ":" to give value for each argument
rule main():
  print bar(a:=1); //print 1 because (b,c := 0) 
  print bar(b:=1); //print 1 because (a,b := 0) 
  print bar(c:=1); //print 1 because (a,b := 0) 
return;  

Rational numbers

In mathematics rational number is any number that can be expressed as the fraction p\q of two integer numbers: numerator "p" of type integer and a non-zero denominator "q" of type natural> 0.
Since "q" may be equal to 1, every binary integer is also a rational number.

Note: Q numbers are approximated numbers.

Other precision constants:

Literal Notation: p/q

It can be used with type inference to create Q numbers:

Example:

make x := 0    ∈ Q; //0     
make a := 1/2  ∈ Q; //0.5   
make b := 1/4  ∈ Q; //0.25  
make c := 1/8  ∈ Q; //0.125 
make d := 1/8  ∈ Q; //0.062
make e := 1/8  ∈ Q; //0.031

Note:

See also: wikipedia

Q Notation

Rational number has a magnitude and precision defined by the user. Q numbers are defined using "fixed point arithmetic"  This is a way of computing fractional numbers and control the precision.

For example: A number format "Q5.2" can store in range (-32.00..31.75) on 8 bits.

make  v ∈ Q5.2;
alter v := -32; //minim value
alter v := 31.75; //maxim value

See also: wikipedia

Typical Q numbers

Next I have predefined some numbers for orientation.

rezolution -> 1\4 ≈ 1\8 ≈ 1\16 ≈ 1\32 ≈ 1\64 ≈
↓ memory space ±0.25 ±0.125 ±0.062 ±0.031 ±0.015
8 bytes Q(5.2 ) Q(4.3 ) Q(3.4 ) Q(2.5 ) Q(1.6 )
16 bytes Q(13.2 ) Q(12.3 ) Q(11.4 ) Q(10.5 ) Q(9.6 )
32 bytes Q(29.2 ) Q(28.3 ) Q(27.4 ) Q(26.5 ) Q(25.6 )
64 bytes Q(61.2 ) Q(60.3 ) Q(59.4 ) Q(58.5 ) Q(56.6 )
128 bytes Q(125.2) Q(124.3) Q(123.4) Q(122.5) Q(121.6)

Note: r ≈ is the approximate resolution.

Examples:

A very large number with high resolution on 64 bit:

Q(50.12)

A number on 32 bit with resolution = 0.0005:

Q(20.11)

Default Q number

Q(14.17)

Default Q number has precision 10⁻⁵ = 2⁻¹⁷ ≈ 0.00001 and occupy 32 bit.

smallest fraction: 1/10000 largest fraction: 32766/2

Approximate comparison

Rational numbers and other numbers can be compared using "≈" instead of "=".

Example:

In next example b = 0.33(3), delta = (b - a) = 0.083

** override default precision
$precision := 0.01;
make a := 0.25; //real
make b := 1/3;  //rational
** using specified precision 0.01 < 0.083
print (a ≈ b); //false
print (a ≈ b ± 0.1); //true
print (a ≈ c ± 0.5); //true
print (b ≈ c ± 0.5); //true

Notes:


Read next: Rules