Access

There are four access expresions:

  • namespace member access
  • routine member access
  • container memeber access
  • field member access

Subprogram access

In most programming languages, it is called “method-call expresion”. A method call consists of an expression (the receiver) followed by a single dot ., an expression path segment, and a parenthesized expression-list:

"3.14".cast(float).pow(2);                  // casting a numbered string to float, then rising it to power of 2

Namespaces access

Accesing namespaces is done through double colon operator :::

use log mod[std] = { fmt::log };            // using the log namespace of fmt
io::console::write_out.echo();              // echoing out

Container access

Array, Vectors, Sequences, Sets

Containers can be indexed by writing a square-bracket-enclosed expression of type int[arch] (the index) after them.

var collection: int = { 5, 4, 8, 3, 9, 0, 1, 2, 7, 6 }

collection[5]                               // get the 5th element staring from front (this case is 0)
collection[-2]                              // get the 3th element starting from back (this case is 1)

Containers can be accessed with a specified range too, by using colon within a square-bracket-enclosed:

syntax meaning
: the whole container
elA:elB from element elA to element elB
:elA from beginning to element elA
elA: from element elA to end
collection[-0]                              // last item in the array
{ 6 }
collection[-1:]                             // last two items in the array
{ 7, 6 }
collection[:-2]                             // everything except the last two items
{ 5, 4, 8, 3, 9, 0, 1, 2 }

If we use double colon within a square-bracket-enclosed then the collection is inversed:

syntax meaning
:: the whole container in reverse
elA::elB from element elA to element elB in reverse
::elA from beginning to element elA in reverse
elA:: from element elA to end in reverse
collection[::]                              // all items in the array, reversed
{ 6, 7, 2, 1, 0, 9, 3, 8, 4, 5 }
collection[2::]                             // the first two items, reversed
{ 4, 5 }
collection[-2::]                            // the last two items, reversed
{ 6, 7 }
collection[::-3]                            // everything except the last three items, reversed
{ 2, 1, 0, 9, 3, 8, 4, 5 }

Matrixes

Matrixes are 2D+ arrays, thus they have a bit more complex acces way:

var aMat = mat[int, int] = { {1,2,3}, {4,5,6}, {7,8,9} };

nMat[[1][0]]                                // this will return 4
                                            // first [] accesses the first dimension, then second [] accesses the second

All other operations are the same like arrays.

Maps

Accesing maps is donw by using the key within square-bracket-enclosed:

var someMap: map[str, int] = { {"prolog", 1}, {"lisp", 2}, {"c", 3} }
someMap["lisp"]                             // will return 2

Axioms

Accesing axioms is more or less like accessing maps, but more verbose and matching through backtracing, and the return is always a vector of elements (empty if no elements are found):

var parent: axi[str, str] = { {"albert","bob"}, {"alice","bob"}, {"bob","carl"}, {"bob","tom"} };

parent["albert",*]                          // this will return strng vector: {"bob"}
parent["bob",*]                             // this will return strng vector: {"carl","tom"}

parent[*,_]                                 // this will match to {"albert", "alice", "bob"}

Matching can be with a vector too:

var parent: axi[str, str] = { {"albert","bob"}, {"alice","bob"}, {"bob","carl"}, {"bob","tom"}, {"maggie","bill"} };
var aVec: vec[str] = { "tom", "bob" };

parent[*,aVec]                              // will match all possible values that have "tom" ot "bob" as second element
                                            // in this case will be a strng vector: {"albert", "alice", "bob"}

a more complex matching:

var class: axi;
class.add({"cs340","spring",{"tue","thur"},{12,13},"john","coor_5"})
class.add({"cs340","winter",{"tue","fri"},{12,13},"mike","coor_5"})
class.add({"cs340",winter,{"wed","fri"},{15,16},"bruce","coor_3"})
class.add({"cs101",winter,{"mon","wed"},{10,12},"james","coor_1"})
class.add({"cs101",spring,{"tue","tue"},{16,18},"tom","coor_1"})

var aClass = "cs340"
class[aClass,_,[_,"fri"],_,*,_]             // this will return string vector: {"mike", bruce}
                                            // it matches everything that has aClass ad "fri" within
                                            // and ignore ones with meh symbol

Avaliability

To check if an element exists, we add : before accessing with []. Thus this will return true if element exists.

var val: vec = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

val:[5]                                     // returns true
val:[15]                                    // returns false


var likes: axi[str, str] = { {"bob","alice"} , {"alice","bob"}, {"dan","sally"} };

likes["bob","alice"]:                       // will return true
likes["sally","dan"]:                       // will return false

In-Place assignment

One of the features that is very important in arrays is that they can assign variables immediately:

var val: vec = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
var even: vec = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}
val[even => Y]                              // this equals to {2, 4, 6, 8, 10} and same time assign to Y
.echo(Y)                                    // will print {2, 4, 6, 8, 10}

This dows not look very much interesting here, you can just as easy assign the whole filtered array to a variable, but it gets interesting for axioms:

var parent: axi[str, str] = { {"albert","bob"}, {"alice","bob"}, {"bob","carl"}, {"bob","tom"}, {"maggie","bill"} };

parent:[* => Y,"bob"]                       // this one returns true if we find a parent of "bob"
                                            // same time it assigns parent to a string vector `Y`

Field access

Field access expressoin accesses fields inside constructs. Here is a recorcalled user:

var user1: user = {
    email = "someone@example.com",
    username = "someusername123",
    active = true,
    sign_in_count = 1
};

fun (user)getName(): str = { result = self.username; };

There are two types of fields that can be accesed within constructs:

  • methods
  • data

Methods

Methods are accesed the same way like routine member access.

user1.getName()

Data

There are multiple ways to acces data within the construct. The easiest one is by dot operator .:

user1.email                                 // accessing the field through dot-accesed-memeber

Another way is by using square bracket enclosed by name:

user1[email]                                // accessing the field through square-bracket-enclosed by name

And lastly, by square bracket enclosed by index:

user1[0]                                    // accessing the field through square-bracket-enclosed by index