-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.json
135 lines (1 loc) · 129 KB
/
index.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
[{"content":"Markdown here\n","description":"test post","id":0,"section":"hub","tags":null,"title":"May 2019","uri":"https://follang.github.io/hub/2019_may/"},{"content":"Markdown here\n","description":"test post","id":1,"section":"hub","tags":null,"title":"April 2019","uri":"https://follang.github.io/hub/2019_april/"},{"content":"Markdown here\n","description":"test post","id":2,"section":"hub","tags":null,"title":"March 2019","uri":"https://follang.github.io/hub/2019_march/"},{"content":"Markdown here\n","description":"test post","id":3,"section":"hub","tags":null,"title":"February 2019","uri":"https://follang.github.io/hub/2019_february/"},{"content":"Markdown here\n","description":"test post","id":4,"section":"hub","tags":null,"title":"January 2019","uri":"https://follang.github.io/hub/2019_january/"},{"content":"Procedures are most common type of routines in Fol. When a procedure is \u0026ldquo;called\u0026rdquo; the program \u0026ldquo;leaves\u0026rdquo; the current section of code and begins to execute the first line inside the procedure. Thus the procedure \u0026ldquo;flow of control\u0026rdquo; is:\n The program comes to a line of code containing a \u0026ldquo;procedure call\u0026rdquo;. The program enters the procedure (starts at the first line in the procedure code). All instructions inside of the procedure are executed from top to bottom. The program leaves the procedure and goes back to where it started from. Any data computed and RETURNED by the procedure is used in place of the procedure in the original line of code. Procedures have side-effects, it can modifies some state variable value(s) outside its local environment, that is to say has an observable effect besides returning a value (the main effect) to the invoker of the operation. State data updated \u0026ldquo;outside\u0026rdquo; of the operation may be maintained \u0026ldquo;inside\u0026rdquo; a stateful object or a wider stateful system within which the operation is performed.\nPassing values The semantics for passing a value to a procedure are similar to those for assigning a value to a variable. Passing a variable to a procedure will move or copy, just as assignment does. If the procedure is stack-based, it will automatically copy the value. If it is heap-based, it will move the value.\npro[] modifyValue(someStr: str) = { someStr = someStr + \u0026quot; world!\u0026quot; } pro[] main: int = { //case1 var[mut] aString: str = \u0026quot;hello\u0026quot;; // a string varibale $aString is declared (in stack as default) modifyValue(aString); // the value is passed to a procedure, since $aVar is in stack, the value is copied .echo(aString) // this prints: \u0026quot;hello\u0026quot;, // value is not changed and still exists here, because was copied //case2 @var[mut] aString: str = \u0026quot;hello\u0026quot;; // a string varibale $bString is declared (in stack with '@') modifyValue(bString); // the value is passed to a procedure, since $aVar is in heap, the value is moved .echo(bString) // this throws ERROR, // value does not exists anymore since it moved and ownership wasn't return } As you can see from above, in both cases, the .echo(varable) does not reach the desired procedure, to print hello world!. In first case is not changed (because is coped), in second case is changed but never returned. To fix the second case, we can just use the .give_back() procedure to return the ownership:\npro[] modifyValue(someStr: str) = { someStr = someStr + \u0026quot; world!\u0026quot; .give_back(someStr) // this returns the ownership (if there is an owner, if not just ignores it) } pro[] main: int = { //case1 var[mut] aString: str = \u0026quot;hello\u0026quot;; // a string varibale $aString is declared (in stack as default) modifyValue(aString); // the value is passed to a procedure, since $aVar is in stack, the value is copied .echo(aString) // this still prints: \u0026quot;hello\u0026quot;, // value is not changed and still exists here, because was copied //case2 @var[mut] aString: str = \u0026quot;hello\u0026quot;; // a string varibale $bString is declared (in stack with '@') modifyValue(bString); // the value is passed to a procedure, since $aVar is in heap, the value is moved .echo(aString) // this now prints: \u0026quot;hello world!\u0026quot;, // value now exists since the ownership is return } Lend parameters But now, we were able to change just the variable that is defined in heap (case two), by moving back the ownership. In case one, since the value is copied, the owner of newly copied value is the procedure itself. So the .give_back() is ignored. To fix this, we use borrowing to lend a value to the procedure\npro[] modifyValue(SOMESTR: str) = { // we use allcaps `SOMESTR` to mark it as borrowable somestr = someStr + \u0026quot; world!\u0026quot; // when we refer, we can both refer with ALLCAPS or lowecaps } pro[] main: int = { //case1 var[mut] aString: str = \u0026quot;hello\u0026quot;; // a string varibale $aString is declared (in stack as default) modifyValue(aString); // the value is lended to the procedure .echo(aString) // this now prints: \u0026quot;hello world!\u0026quot;, //case2 @var[mut] aString: str = \u0026quot;hello\u0026quot;; // a string varibale $bString is declared (in heap with '@') modifyValue(aString); // the value is lended to the procedure .echo(aString) // this now prints: \u0026quot;hello world!\u0026quot;, } So to make a procedure borrow a varibale it uses all caps name A_VAR.\nRemember that two variables are the same if have same characters (does not matter the caps)\n pro[] borrowingProcedure(aVar: str; BVAR: bol; cVar, DVAR: int) To call this procedure, the borrowed parameters always shoud be a variable name and not a direct value:\nvar aBool, anInt = true, 5 borrowingProcedure(\u0026quot;get\u0026quot;, true, 4, 5) // this will throw an error, cos it expects borrowable not direct value borrowingProcedure(\u0026quot;get\u0026quot;, aBool, 4, anInt) // this is the proper way When the value is passed as borrowable in procedure, by default it gives premission to change, so the same as var[mut, bor] as disscussed here.\nReturn ownership Return values can be though as return of ownership too. The ownership of a variable follows the same pattern every time: assigning a value to another variable moves or copies it.\npro main(): int = { var s1 = givesOwnership(); // the variable $s1 is given the ownership of the procedure's $givesOwnership return .echo(s1) // prints \u0026quot;hi\u0026quot; var s2 = returnACopy(); // the variable $s2 is given the ownership of the procedure's $returnACopy return .echo(s2) // prints: \u0026quot;there\u0026quot; } pro givesOwnership(): str = { // This procedure will move its return value into the procedure that calls it @var someString = \u0026quot;hi\u0026quot;; // $someString comes into scope return someString // $someString is returned and MOVES out to the calling procedure } pro returnACopy(): int = { // This procedure will move its return value into the procedure that calls it var anotherString = \u0026quot;there\u0026quot; // $anotherString comes into scope return anotherString // $anotherString is returned and COPIES out to the calling procedure } When a variable that includes data on the heap goes out of scope, the value will be cleaned up automatically by .de_alloc() unless the data has been moved to be owned by another variable, in this case we give the ownership to return value. If the procedure with the retun value is not assigned to a variable, the memory will be freed again.\nWe can even do a transfer of ownership by using this logic:\npro main(): int = { @var s2 = \u0026quot;hi\u0026quot;; // $s2 comes into scope (allocatd in the heap) var s3 = transferOwnership(s2); // $s2 is moved into $transferOwnership procedure, which also gives its return ownership to $s3 .echo(s3) // prints: \u0026quot;hi\u0026quot; .echo(s2) // this throws an error, $s2 is not the owner of anything anymore } pro transferOwnership(aString: str): str = { // $aString comes into scope return aString // $aString is returned and moves out to the calling procedure } This does not work with borrowing though. When a variable is lended to a procedure, it has permissions to change, but not lend to someone else. The only thing it can do is make a .deep_copy() of it:\npro main(): int = { @var s2 = \u0026quot;hi\u0026quot;; // $s2 comes into scope (allocatd in the heap) var s3 = transferOwnership(s2); // $s2 is moved into $transferOwnership procedure, which also gives its return ownership to $s3 .echo(s3) // prints: \u0026quot;hi\u0026quot; .echo(s2) // prints: \u0026quot;hi\u0026quot; too } pro transferOwnership((aString: str)): str = { // $aString comes into scope which is borrowed return aString // $aString is borrowed, thus cant be lended to someone else // thus, the return is a deep_copy() of $aString } ","description":"","id":10,"section":"docs","tags":null,"title":"Procedures","uri":"https://follang.github.io/docs/500_items/routines/procedures/"},{"content":"An import declaration states that the source file containing the declaration depends on functionality of the imported package and enables access to exported identifiers of that package.\nSyntax to import a library is:\nuse package_name: mod = { path } There are two type of import declartions:\n system libraries local libraries System libraries This is how including other libraries works, for example include fmt module from standard library:\nuse fmt: std = {\u0026quot;fmt\u0026quot;}; pro main: ini = { fmt::log.warn(\u0026quot;Last warning!...\u0026quot;) } To use only the log namespace of fmt module:\nuse log: std = {\u0026quot;fmt/log\u0026quot;}; pro[] main: int = { log.warn(\u0026quot;Last warning!...\u0026quot;) } But let\u0026rsquo;s say you only wanna use ONLY the warn functionality of log namespace from fmt module:\nuse warn std = {\u0026quot;fmt/log.warn\u0026quot;}; pro[] main: int = { warn(\u0026quot;Last warning!...\u0026quot;) } Local libraries To include a local package (example, package name bender), then we include the folder where it is, followed by the package name (folder is where files are located, package is the name defned with mod[])\nuse bend: loc = {\u0026quot;../folder/bender\u0026quot;}; Then to acces only a namespace:\nuse space: loc = {\u0026quot;../folder/bender/space\u0026quot;}; URL libraries Libraries can be directly URL imported:\nuse space: url = {\u0026quot;https://github.com/follang/std\u0026quot;}; ","description":"","id":11,"section":"docs","tags":null,"title":"Import","uri":"https://follang.github.io/docs/600_modules/import/"},{"content":"Functions compared to procedure are pure. A pure function is a function that has the following properties:\n Its return value is the same for the same arguments (no variation with local static variables, non-local variables, mutable reference arguments or input streams from I/O devices). Its evaluation has no side effects (no mutation of local static variables, non-local variables, mutable reference arguments or I/O streams). Thus a pure function is a computational analogue of a mathematical function. Pure functions are declared with fun[]\nfun[] add(el1, el2: int[64]): int[64] = { result = el1 + el2 } var[] add = [fun(el1, el2: int): int]{ result = el1 + el2 } Functions in FOL are lazy-initialized.\n So it is an evaluation strategy which delays the evaluation of the function until its value is needed. You call a function passing it some arguments that were expensive to calculate and then the function don’t need all of them due to some other arguments.\nConsider a function that logs a message:\nprint.debug(\u0026quot;Called foo() passing it \u0026quot; + .to_string(argument_a) + \u0026quot; and \u0026quot; + .to_string(argument_b)); The log library has various log levels like “debug”, “warning”, “error” etc. This allows you to control how much is actually logged; the above message will only be visible if the log level is set to the “debug” level. However, even when it is not shown the string will still be constructed and then discarded, which is wasteful.\nSince Fol supports first class functions, it allows functions to be assigned to variables, passed as arguments to other functions and returned from other functions.\n Anonymous functoins Anonymous function is a function definition that is not bound to an identifier. These are a form of nested function, in allowing access to variables in the scope of the containing function (non-local functions).\nStaring by assigning a anonymous function to a vriable:\nvar f = [fun(a, b: int)]{ // variable assignmet to function return a + b } .echo(f(5,6)) // prints 11 It is also possible to call a anonymous function without assigning it to a variable.\n[fun(a, b: int)]{ `define anonymous function` .echo(a + b) }(5, 6) `calling anonymous function` Higer-order functions A higher-order function is a function that takes a function as an argument. This is commonly used to customize the behavior of a generically defined function, often a looping construct or recursion scheme.\nThey are functions which do at least one of the following:\n takes one or more functions as arguments returns a function as its result //function as parameter fun[] add1(adder: rut[(x: int): int]): int = { return adder(x + n) } //function as return fun[] add2(): rut[(x: int): int] = { var f = [fun(a, b: int): int]{ return a + b } return f } rut representr a routine (it can be: fun, pro, or log).\nClosures Functions can appear at the top level in a module as well as inside other scopes, in which case they are called nested functions. A nested function can access local variables from its enclosing scope and if it does so it becomes a closure. Any captured variables are stored in a hidden additional argument to the closure (its environment) and they are accessed by reference by both the closure and its enclosing scope (i.e. any modifications made to them are visible in both places). The closure environment may be allocated on the heap or on the stack if the compiler determines that this would be safe.\nThere are two types of closures:\n anonymous named Anonymus closures automatically capture variables, while named closures need to be specified what to capture. For capture we use the [] just before the type declaration.\nfun[] add(n: int): int = { fun added(x: int)[n]: int = { // we make a named closure return x + n // variable $n can be accesed because we have captured ti } return adder(5) } fun[] add(n: int): int = { return [fun(x: int): int]{ // we make a anonymous closure return x + n // variable $n can be accesed from within the nested function }(5) } Currying Currying is converting a single function of \u0026ldquo;n\u0026rdquo; arguments into \u0026ldquo;n\u0026rdquo; functions with a \u0026ldquo;single\u0026rdquo; argument each. Given the following function:\nfun f(x,y,z) = { z(x(y));} When curried, becomes:\nfun f(x) = { [fun(y)]{ [fun(z)]{ z(x(y)) } } } And calling it woud be like:\nf(x)(y)(z) However, the more iportant thing is taht, currying is a way of constructing functions that allows partial application of a function’s arguments. What this means is that you can pass all of the arguments a function is expecting and get the result, or pass a subset of those arguments and get a function back that’s waiting for the rest of the arguments.\nfun calc(x) = { return [fun(y)]{ return [fun (z): int]{ return x + y + z } } } var value = calc(5)(6) // this is okay, return value is a function var another int = value(8) // this completes the function by calling the function above var allIn: int = calc(5)(6)(8) // or this as alternative A more verbose way of the function above is:\nfun calc(x): [fun(y): [fun (z): int]] = { return [fun(y): [fun (z): int]]{ return [fun (z): int]{ return x + y + z } } } Generators A generator is very similar to a function that returns an array, in that a generator has parameters, can be called, and generates a sequence of values. However, instead of building an array containing all the values and returning them all at once, a generator yields the values one at a time, which requires less memory and allows the caller to get started processing the first few values immediately. In short, a generator looks like a function but behaves like an iterator.\nFor a function to be a generator (thus to make the keyword yeild accesable), it needs to return a type of container: arr, vec, seq, mat but not set, any.\nfun someIter: vec[int] = { var curInt = 0; loop(){ yeild curInt.inc(1) } } ","description":"","id":13,"section":"docs","tags":null,"title":"Functions","uri":"https://follang.github.io/docs/500_items/routines/functions/"},{"content":"At least two linguistic mechanisms are necessary to make the computations in programs flexible and powerful: some means of selecting among alternative control flow paths (of statement execution) and some means of causing the repeated execution of statements or sequences of statements. Statements that provide these kinds of capabilities are called control statements. A control structure is a control statement and the collection of statements whose execution it controls. This set of statements is in turn generally structured as a block, which in addition to grouping, also defines a lexical scope.\nThere are two types of control flow mechanisms:\n choice - when loop - loop guard - if Choice type when(){ case(condition){} case(condition){} _ {} }; when(variable){ is (value){}; is (value){}; _ {}; }; when(variable){ in (iterator){}; in (iterator){}; _ {}; }; when(variable){ has (member){}; has (member){}; _ {}; }; when(variable){ of (type){}; of (type){}; _ {}; }; when(type){ on (channel){}; on (channel){}; }; Condition when() { case (x == 6){ // implementation } case (y.set()){ // implementation } _ { // default implementation } } Valueation when(x) { is (6){ // implementation } is (\u0026gt;7){ // implementation } _ { // default implementation } } Iteration when(2 * x) { in ({0..4}){ // implementation } in ({ 5, 6, 7, 8, }){ // implementation } _ { // default implementation } } Contains when({4,5,6,7,8,9,0,2,3,1}) { has (5){ // implementation } has (10){ // implementation } _ { // default implementation } } Generics when(T) { of (int){ // implementation } of (str){ // implementation } _ { // default implementation } } Channel when(str) { on (channel){ // implementation } on (channel){ // implementation } _ { // default implementation } } Loop type loop(condition){}; loop(iterable){}; Condition loop( x == 5 ){ // implementation }; Enumeration loop( x in {..100}){ // implementation } loop( x in {..100}) if ( x % 2 == 0 )){ // implementation } loop( x in {..100} if (( x in somearra ) and ( x in anotherarray ))){ // implementation } Iteration loop( x in array ){ // implementation } Guard type The if statement can be used as guard in both when statement and loop statement:\n loop( x in {..100} if (( x in somearra ) and ( x in anotherarray ))){ // implementation } when(x) { is (6) if (6 of (int)){ // implementation } is (7) if (7 in (somearray)){ // implementation } * { // default implementation }http://spack.rtfd.io/ } ","description":"","id":14,"section":"docs","tags":null,"title":"Control","uri":"https://follang.github.io/docs/200_expressions/200_sta/control/"},{"content":"There is another type of routine, called method, but it can be either a pure function either a procedure. A method is a piece of code that is called by a name that is associated with an object where it is implicitly passed the object on which it was called and is able to operate on data that is contained within the object.\nThey either are defined inside the object, or outside the object then the object in which they operate is passed like so (just like in Golang):\npro (object)getDir(): str = { result = self.dir; }; ","description":"","id":16,"section":"docs","tags":null,"title":"Methods","uri":"https://follang.github.io/docs/500_items/routines/methods/"},{"content":"Each file in a folder (with extension .fol) is part of a package. There is no need for imports or other things at the top of the file. They share the same scope, and each declaration is order independent for all files.\nNamespaces A namespace can be defined in a subfolder of the main foler. And they can be nested.\nTo acces the namespace there are two ways:\n direct import with use or code access with :: Direct import use aNS: loc = { \u0026quot;home/folder/printing/logg\u0026quot; } pro[] main: int = { logg.warn(\u0026quot;something\u0026quot;) } Code access use aNS: loc = { \u0026quot;home/folder/printing\u0026quot; } pro[] main: int = { printing::logg.warn(\u0026quot;something\u0026quot;) } Blocks Block statement is used for scopes where members get destroyed when scope is finished. And there are two ways to define a block:\n unnamed blocks and named blocks Unnamed blocks Are simply scopes, that may or may not return value, and are represented as: { //block }, with . before the brackets for return types and _ for non return types:\npro[] main: int = { _{ .echo(\u0026quot;simple type block\u0026quot;) } .echo(.{ return \u0026quot;return type block\u0026quot; }) } Named blocks Blocks can be used as labels too, when we want to unconditionally jump to a specific part of the code.\npro[] main: int = { def block: blk[] = { // $block A named block that can be referenced // implementation } def mark: blk[] // $mark A named block that can be referenced, usually for \u0026quot;jump\u0026quot; statements } ","description":"","id":19,"section":"docs","tags":null,"title":"Declaration","uri":"https://follang.github.io/docs/600_modules/blocks/"},{"content":"Logicals, which are logic routines, and represent logic programming, state the routine as a set of logical relations (e.g., a grandparent is the parent of a parent of someone). Such rutines are similar to the database languages. A program is executed by an “inference engine” that answers a query by searching these relations systematically to make inferences that will answer a query.\nOne of the main goals of the development of symbolic logic hasbeen to capture the notion of logical consequence with formal, mechanical, means. If the conditions for a certain class of problems can be formalized within a suitable logic as a set of premises, and if a problem to be solved can bestated as a sentence in the logic, then a solution might be found by constructing a formal proof of the problem statement from the premises\n Declaration In FOL, logic programming is considered as a first class citzen with axioms (axi) as facts and logicals (log) as rules, thus resembling Prolog language. For example:\nFacts Declaring a list of facts (axioms)\nvar likes: axi[str, str] = { {\u0026quot;bob\u0026quot;,\u0026quot;alice\u0026quot;} , {\u0026quot;alice\u0026quot;,\u0026quot;bob\u0026quot;}, {\u0026quot;dan\u0026quot;,\u0026quot;sally\u0026quot;} }; Rules Declaring a rule that states if A likes B and B likes A, they are dating\nlog dating(a, b: str): bol = { likes:[a,b] and likes:[b,a] } Declaring a rule that states if A likes B and B likes A, they are just friends\nlog frends(a, b): bol = { likes:[a,b] or likes:[b,a] } Rules can have only facts and varibles within\n Return A logical log can return different values, but they are either of type bol, or of type container (axioms axi or vectors vec):\nLets define a axiom of parents and childrens called parents and another one of parents that can dance called dances:\nvar parent: axi[str, str] = { {\u0026quot;albert\u0026quot;,\u0026quot;bob\u0026quot;}, {\u0026quot;albert\u0026quot;,\u0026quot;betty\u0026quot;}, {\u0026quot;albert\u0026quot;,\u0026quot;bill\u0026quot;}, {\u0026quot;alice\u0026quot;,\u0026quot;bob\u0026quot;}, {\u0026quot;alice\u0026quot;,\u0026quot;betty\u0026quot;}, {\u0026quot;alice\u0026quot;,\u0026quot;bill\u0026quot;}, {\u0026quot;bob\u0026quot;,\u0026quot;carl\u0026quot;}, {\u0026quot;bob\u0026quot;,\u0026quot;tom\u0026quot;} }; var dances axi[str] = { \u0026quot;albert\u0026quot;, \u0026quot;alice\u0026quot;, \u0026quot;carl\u0026quot; }; Boolean Here we return a boolean bol. This rule check if a parent can dance:\nlog can_parent_dance(a: str): bol = { parent:[a,_] and dances:[a] } can_parent_dance(\u0026quot;albert\u0026quot;) // return true, \u0026quot;albert\u0026quot; is both a parent and can dance can_parent_dance(\u0026quot;bob\u0026quot;) // return false, \u0026quot;bob\u0026quot; is a parent but can't dance can_parent_dance(\u0026quot;carl\u0026quot;) // return false, \u0026quot;carl\u0026quot; is not a parent Lets examine this:\nparent:[a,_] and dances:[a]\nthis is a combintion of two facts. Here we say if a is parent of anyone (we dont care whose, that\u0026rsquo;s why we use meh symbol [a,_]) and if true, then we check if parent a (since he is a parent now, we fact-checked) can dance.\nVector The same, we can create a vector of elements. For example, if we want to get the list of parents that dance:\nlog all_parents_that_dance(): vec[str] = { parent:[*-\u0026gt;X,_] and dances:[X-\u0026gt;Y] Y } all_parents_that_dance() // this will return a string vector {\u0026quot;albert\u0026quot;, \u0026quot;alice\u0026quot;} Now lets analyze the body of the rule:\nparent:[*-\u0026gt;X,_] and dances:[X-\u0026gt;Y] Y Here are a combination of facts and variable assignment through silents. Silents are a single letter identifiers. If a silent constant is not declared, it gets declared and assigned in-place.\nTaking a look each line:\nparent:[X,_] and\nthis gets all parents ([*-\u0026gt;X,_]),and assign them to silent X. So, X is a list of all parents.\nthen:\ndances[X-\u0026gt;Y]:\nthis takes the list of parents X and checks each if they can dance, and filter it by assigning it to Y so [X-\u0026gt;Y] it will have only the parents that can dance.\nthen:\nY\nthis just returns the list Y of parents that can dance.\nRelationship If A is object and objects can be destroyed, then A can be destroyed. As a result axioms can be related or conditioned to other axioms too, much like facts.\nFor example: if carl is the son of bob and bob is the son of albert then carl must be the grandson of albert:\nlog grandparent(a: str): vec[str] = { parent[*-\u0026gt;X,a]: and parent[*-\u0026gt;Y,X]: Y } Or: if bob is the son of albert and betty is the doughter of albert, then bob and betty must be syblings:\nlog are_syblings(a, b: str): vec[str] = { parent[*-\u0026gt;X,a]: and parent[X-\u0026gt;Y,b]: Y } Same with uncle relationship:\nvar brothers: axi[str] = { {\u0026quot;bob\u0026quot;:\u0026quot;bill\u0026quot;}, {\u0026quot;bill\u0026quot;,\u0026quot;bob\u0026quot;} }; log has_uncle(a: str): vec[str] = { parent[*-\u0026gt;Y,a]: and brothers[Y,*-\u0026gt;Z]:; Z } Conditional facts Here an example, the axioms hates will add a memeber romeo only if the relation x is satisfied:\nvar stabs: axi = {{\u0026quot;tybalt\u0026quot;,\u0026quot;mercutio\u0026quot;,\u0026quot;sword\u0026quot;}} var hates: axi; log romeHates(X: str): bol = { stabs[X,\u0026quot;mercutio\u0026quot;,_]: } hates+[\u0026quot;romeo\u0026quot;,X] if (romeHates(X)); Anonymous logicals Conditional facts can be added with the help of anonymous logicals/rules:\neats+[x,\u0026quot;cheesburger\u0026quot;] if (eats[x,\u0026quot;bread\u0026quot;] and eats[X,\u0026quot;cheese\u0026quot;]); eats+[x:\u0026quot;cheesburger\u0026quot;] if (log (a: str): bol = { eats[a,\u0026quot;bread\u0026quot;]: and eats[a,\u0026quot;cheese\u0026quot;]: }(x)); Nested facts var line: axi = { {{4,5},{4,8}}, {{8,5},{4,5}} } log vertical(line: axi): bol = { line[*-\u0026gt;A,*-\u0026gt;B]: and A[*-\u0026gt;X,Y*-\u0026gt;]: and B[X,*-\u0026gt;Y2]: } log horizontal(line: axi): bol = { line[*-\u0026gt;A,*-\u0026gt;B]: and A[*-\u0026gt;X,*-\u0026gt;Y]: and B[*-\u0026gt;X2,Y]: } assert(vertical(line.at(0)) assert(horizontal(line.at(1)) Filtering Another example of filtering a more complex axion:\nvar class: axi; class.add({\u0026quot;cs340\u0026quot;,\u0026quot;spring\u0026quot;,{\u0026quot;tue\u0026quot;,\u0026quot;thur\u0026quot;},{12,13},\u0026quot;john\u0026quot;,\u0026quot;coor_5\u0026quot;}) class.add({\u0026quot;cs340\u0026quot;,winter,{\u0026quot;wed\u0026quot;,\u0026quot;fri\u0026quot;},{15,16},\u0026quot;bruce\u0026quot;,\u0026quot;coor_3\u0026quot;}) log instructor(class: str): vec[str] = { class[class,_,[_,\u0026quot;fri\u0026quot;],_,*-\u0026gt;X,_] X } ","description":"","id":20,"section":"docs","tags":null,"title":"Logicals","uri":"https://follang.github.io/docs/500_items/routines/logicals/"},{"content":"Here are some of the ways that variables can be defined:\nvar[pub,mut] somename: num[i32] = 98; var[pub,exp] snotherone: str = \u0026quot;this is a string\u0026quot; var[~] yetanother = 192.56 var[+] shortlet = true var anarray: arr[str,3] = { \u0026quot;one\u0026quot;, \u0026quot;two\u0026quot;, \u0026quot;three\u0026quot; } var asequence : seq[num[i8]] = { 20, 25, 45, 68, 73,98 } var multiholder: set[num, str] = { 12, \u0026quot;word\u0026quot; } var anothermulti: set[str, seq[num[f32]]] = { \u0026quot;string\u0026quot;, {5.5, 4.3, 7, .5, 3.2} } var shortvar = anothermulti[1][3] var anymulti: any = {5, 10, \u0026quot;string\u0026quot;, {'a',\u0026quot;word\u0026quot;,{{0, \u0026quot;val\u0026quot;},{1, \u0026quot;nal\u0026quot;}}}, false} var getSomeVal = anymulti[3][2][0][0] | \u0026lt; 15 | shortvar Assignments Following the general rule of FOL:\ndeclaration[options] name: type[options] = { implementation; }; then declaring a new variable is like this:\nvar[pub] aVar: int[32] = 64 however, the short version can be used too, and the compiler figures out at compute time the type:\nvar shortVar = 24; // compiler gives this value of `int[arch]` When new variable is created, and uses an old variable to assign, the value is cloned, not referenced:\npro[] main: int = { var aVar: int = 55; var newVar: int = \u0026lt;move\u0026gt;aVar; // aVar gets moved to newVar thus after this point does not exist .assert(\u0026lt;ref\u0026gt;aVar == \u0026lt;ref\u0026gt;newVar) // this will panic because aVar doesn't exists it was moved } Two variables can not have the same memory location, unless we either borrow, or use pointers.\nVariables can be assigned to an output of a function:\npro[] main: int = { fun addFunc(x, y: int): int = { return x + y; } var aVar: int = addFunc(4, 5); } Piping / Ternary Piping can be used as ternary operator. More about piping can be found here. Here is an example, the code below basically says: if the function internally had an error, don\u0026rsquo;t exit the program, but assign another value (or default value) to the variable:\npro[] main: int = { fun addFunc(x, y: int): int = { return x + y; } var aVar: int = addFunc(4, 5) | result \u0026gt; 8 | return 6; } Borrowing If we want to reference a variable, the easiest way is to borrow the variable, use inside another scope (or the same) and return it back. If the ownership is not returned manually, by the end of the scope, it gets returned automatically.\npro[] main: int = { var[~] aVar: int = 55; { var newVar: int = \u0026lt;borrow\u0026gt;aVar // \u0026lt;borrow\u0026gt; notation represents borrowing .echo(newVar) // this return 55 } .echo(\u0026lt;ref\u0026gt;aVar) // here $aVar it accesible, as the ownership returns at the end of the scope .echo(\u0026lt;ref\u0026gt;newVar) // we cant access the variable because the scope has ended } More on borrowing you can find here\nOptions As with all other blocks, var have their options: var[opt]:\nOptions can be of two types:\n flags eg. var[mut] values eg. var[pri=2] Flag options can have symbol aliases eg. var[mut] is the somename as var[~].\n| opt | s | type | description | control | ---------------------------------------------------------------------------------------------- | mut | ~ | flag | making a variable mutable | mutability | | imu | | flag | making a variable imutable (default) | | | sta | ! | flag | making a variable a static | | | rac | ? | flag | making a variable reactive | | ---------------------------------------------------------------------------------------------- | exp | + | flag | making a global variable pubic | visibility | | nor | | flag | making a global variable normal (default) | | | hid | - | flag | making a global variable hidden | | Alternatives There is a shorter way for variables using alternatives, for example, instead of using var[+], a leaner +var can be used instead.\ndef shko: mod[] = { +var aVar: int = 55; pro[] main: int { .echo(\u0026lt;ref\u0026gt;aVar) } } However, when we use two option in varable, only one can use the alternative form, so instead of using var[mut,exp], this can be used +var[mut] or +var[~], or vice varsa ~var[exp] or ~var[+]:\ndef shko: mod[] = { +var[mut] aVar: int = 55; pro[] main: int { .echo(\u0026lt;ref\u0026gt;aVar) } } Types Immutable types (constants) By default when a variable is defined without options, it is immutable type, for example here an intiger variable:\npro[] main: int = { var aNumber: int = 5; aNumber = 54; // reassigning varibale $aNumber thorws an error } Mutable types If we want a variable to be mutable, we have to explicitly pass as an option to the variable var[mut] or var[~]:\npro[] main: int = { var[mut] aNumber: int = 5 var[~] anotherNumber: int = 24 aNumber, anotherNumber = 6 // this is completely fine, we assign two wariables new values } Reactive types Reactive types is a types that flows and propagates changes.\nFor example, in an normal variable setting, var a = b + c would mean that a is being assigned the result of b + c in the instant the expression is evaluated, and later, the values of b and c can be changed with no effect on the value of a. On the other hand, declared as reactive, the value of a is automatically updated whenever the values of b or c change, without the program having to re-execute the statement a = b + c to determine the presently assigned value of a.\npro[] main: int = { var[mut] b, c = 5, 4; var[rac] a: int = b + c .echo(\u0026lt;ref\u0026gt;a) // prints 9 c = 10; .echo(\u0026lt;ref\u0026gt;a) // now it prints 10 } Static types Is a variable which allows a value to be retained from one call of the function to another, meaning that its lifetime declaration. and can be used as var[sta] or var[!]. This variable is special, because if it is initialized, it is placed in the data segment (aka: initialized data) of the program memory. If the variable is not set, it is places in .bss segmant (aka: uninitialized data)\npro[] main: int = { { var[!] aNumber: int = 5 } { .echo(\u0026lt;ref\u0026gt;aNumber) // it works as it is a static variable. } } Scope As disscussed before, files with same name share the same functions and global variables. However, those variables and functions can\u0026rsquo;t be accesed if the whole module is imported in another project. In order for a variable to be accest by the importer, it needs to be have the exp flag option, so var[exp], or var[+]\nmodule shko, file1.fol\ndef shko: mod[] = { fun[+] add(a, b: int) = { return a + b } fun sub(a, b: int) = { return a - b } } module vij, file1.fol\nuse shko: mod[loc] = {../folder/shko} def vij: mod[] = { pro[] main: int { .echo(add( 5, 4 )) // this works perfectly fine, we use a public/exported function .echo(sub( 5, 4 )) // this throws an error, we are trying use a function that is not visible to other libraries } } There is even the opposite option too. If we want a function/variable to be only used inside the file ( so same package but only for that file ) then we use hid option flag: var[hid] or var[-]\nfile1.fol\ndef shko: mod[] = { var[-] aVar: str = \u0026quot;yo, sup!\u0026quot; } file2.fol\ndef shko: mod[] = { pro[] main: int { .echo(\u0026lt;ref\u0026gt;aVar) } // this will thro an error (cos $aVar is declared private/hidden) } Multiple Many to many Many variables can be assigned at once, This is especially usefull, if variables have same options but different types eg. variable is mutabe and exported:\n~var[exp] oneVar: int[32] = 24, twoVar = 13, threeVar: string = \u0026quot;shko\u0026quot;; Or to assign multiple variables of the same type:\n~var[exp] oneVar, twoVar: int[32] = 24, 13; To assign multiple variables of multiple types, the type is omitted, however, this way we can not put options on the type (obviously, the default type is assign by compiler):\n~var[exp] oneVar, twoVar, threeVar = 24, 13, \u0026quot;shko\u0026quot;; Another \u0026ldquo;shameless plagiarism\u0026rdquo; from golang can be used by using ( ... ) to group variables:\n~var[exp] ( oneVar: int[32] = 13, twoVar: int[8] = 13, threeVar: str = \u0026quot;shko\u0026quot;, ) Many to one Many variables of the same type can be assigned to one output too:\nvar oneVar, twoVar: int[8] = 2; However, each of them gets a copy of the variable on a new memory address:\n.assert(\u0026amp;oneVar == \u0026amp;twoVar) // this will return false One to many And lastly, one variable can be assigned to multiple ones. This by using container types:\noneVar grouppy: seq[int] = { 5, 2, 4, 6 } Or a more complicated one:\nvar anothermulti: set[str, seq[num[f32]]] = { \u0026quot;string\u0026quot;, {5.5, 4.3, 7, .5, 3.2} } Or a very simple one:\nvar simplemulti: any = { 5, 6, {\u0026quot;go\u0026quot;, \u0026quot;go\u0026quot;, \u0026quot;go\u0026quot;} } Containers Containers are of special type, they hold other types within. As described before, there are few of them\nAccess To acces container variables, brackets like this [] are use:\nvar shortvar = anothermulti[1][3] // compiler will copy the value `anothermulti[1][3]` (which is a float) to a new memory location ","description":"","id":21,"section":"docs","tags":null,"title":"Variables","uri":"https://follang.github.io/docs/500_items/variables/"},{"content":"Blocks defined with type tst, have access to the module (or namespace) defined in tst[\u0026quot;name\u0026quot;, access].\ndef test1: tst[\u0026quot;sometest\u0026quot;, shko] = {} def \u0026quot;some unit testing\u0026quot;: tst[shko] = {} ","description":"","id":25,"section":"docs","tags":null,"title":"Tests","uri":"https://follang.github.io/docs/600_modules/tests/"},{"content":"An alias declaration binds an identifier to an existing type. All the properties of the existing type are bound to the alias too.\nThere are two type of aliasing:\n aliasing extending Aliasing ali I5: arr[int, 5]; So now the in the code, instead of writing arr[int, 5] we could use I5:\n~var[pub] fiveIntigers: I5 = { 0, 1, 2, 3, 4, 5 } Another example is creating a rgb type that can have numbers only form 0 to 255:\nali rgb: int[8][.range(255)] ; // we create a type that holds only number from 0 to 255 ali rgbSet: set[rgb, rgb, rgb]; // then we create a type holding the `rgb` type Alias declaration are created because they can simplify using them multiple times, their identifier (their name) may be expressive in other contexts, and–most importantly–so that you can define (attach) methods to it (you can\u0026rsquo;t attach methods to built-in types, nor to anonymous types or types defined in other packages).\nAttaching methods is of outmost importance, because even though instead of attaching methods you could just as easily create and use functions that accept the \u0026ldquo;original\u0026rdquo; type as parameter, only types with methods can implement blueprint standards blu[] that list/enforce those methods, and you can\u0026rsquo;t attach methods to certain types unless you create a new type derived from them.\nExtending Extensions add new functionality to an existing constructs. This includes the ability to extend types for which you do not have access to the original source code (known as retroactive modeling).\nali[ext] type: type; For example, adding a print function to the default integer type int:\nali[ext] int: int; pro (int)print(): non = { .echo(self) } pro main: int = { 5.print() // method print on int } Or turning a string str into a vector of characters:\nali[ext] str: str; fun (str)to_array(): vec[chr] = { loop(x in self){ yeild x; } } pro main(): int = { var characters: vec[chr] = \u0026quot;a random str\u0026quot;.to_array(); .echo(characters) // will print: {\u0026quot;a\u0026quot;,\u0026quot; \u0026quot;,\u0026quot;r\u0026quot;,\u0026quot;a\u0026quot;,\u0026quot;n\u0026quot;,\u0026quot;d\u0026quot;,\u0026quot;o\u0026quot;,\u0026quot;m\u0026quot;,\u0026quot; \u0026quot;,\u0026quot;s\u0026quot;,\u0026quot;t\u0026quot;,\u0026quot;r\u0026quot;} } ","description":"","id":27,"section":"docs","tags":null,"title":"Aliases","uri":"https://follang.github.io/docs/500_items/constructs/aliases/"},{"content":"Structs are the way to declare new type of data. A struct binds an identifier, the type name, to a type.\nA struct definition creates a new, distinct type and are few of them in FOL:\n records entries Definition Records A record is an aggregate of data elements in which the individual elements are identified by names and types and accessed through offsets from the beginning of the structure. There is frequently a need in programs to model a collection of data in which the individual elements are not of the same type or size. For example, information about a college student might include name, student number, grade point average, and so forth. A data type for such a collection might use a character string for the name, an integer for the student number, a floating- point for the grade point average, and so forth. Records are designed for this kind of need.\nIt may appear that records and heterogeneous set are the same, but that is not the case. The elements of a heterogeneous set[] are all references to data objects that reside in scattered locations, often on the heap. The elements of a record are of potentially different sizes and reside in adjacent memory locations. Records are normally used as encapsulation structures, rather than data structures.\ntyp user: rec = { var username: str; var email: str; var sign_in_count: int[64]; var active: bol; }; Records as classes Calsses are the way that FOL can apply OOP paradigm. They basically are a glorified record. Instead of methods to be used fom outside the body, they have the method declaration within the body. For example, creating an class computer and its methods within the body:\n~typ[pub] computer: rec = { var[pub] brand: str; var[pub] memory: int[16]; +fun getType(): str = { brand + .to_string(memory) }; }; var laptop: computer = { member1 = value, member2 = value }; .echo(laptop.getType()); Entries Is an a group of constants (identified with ent) consisting of a set of named values called elements.\ntyp color: ent = { var BLUE: str = \u0026quot;#0037cd\u0026quot; var RED str = \u0026quot;#ff0000\u0026quot; var BLACK str = \u0026quot;#000000\u0026quot; var WHITE str = \u0026quot;#ffffff\u0026quot; }; if( something == color.BLUE ) { doathing } else { donothing } Entries as enums Unums represent enumerated data. An enumeration type (or enum type) is a value type defined by a set of named constants of the underlying integral numeric type.\ntyp aUnion: ent = { var BLUE, RED, BLACK, WHITE: int[8] = {..3} } Initializaion To use a record after we’ve defined it, we create an instance of that record by specifying concrete values for each of the fields. We create an instance by stating the name of the record and then add curly brackets containing key: value pairs, where the keys are the names of the fields and the values are the data we want to store in those fields. We don’t have to specify the fields in the same order in which we declared them in the record. In other words, the record definition is like a general template for the type, and instances fill in that template with particular data to create values of the type.\n@var user1: user = { email = \u0026quot;[email protected]\u0026quot;, username = \u0026quot;someusername123\u0026quot;, active = true, sign_in_count = 1, }; Named initialization: @var[mut] user1: user = { email = \u0026quot;[email protected]\u0026quot;, username = \u0026quot;someusername123\u0026quot;, active = true, sign_in_count = 1 } Ordered initialization @var[mut] user1: user = { \u0026quot;[email protected]\u0026quot;, \u0026quot;someusername123\u0026quot;, true, 1 } Accessing To get a specific value from a record, we can use dot notation or the access brackets. If we wanted just this user’s email address, we could use user1.email or user1[email] wherever we wanted to use this value. If the instance is mutable, we can change a value by assigning into a particular field. Note that the entire instance must be mutable; FOL doesn’t allow us to mark only certain fields as mutable.\n@var[mut] user1: user = { email = \u0026quot;[email protected]\u0026quot;, username = \u0026quot;someusername123\u0026quot;, active = true, sign_in_count = 1, }; user1.email = \u0026quot;[email protected]\u0026quot; user1[username] = \u0026quot;anotherusername\u0026quot; Returning As with any expression, we can construct a new instance of the record as the last expression in the function body to implicitly return that new instance. As specified in function return, the final expression in the function will be used as return value. For this to be used, the return type of the function needs to be defined (here is defined as user) and this can be used only in one statement body. Here we have declared only one variable user1 and that itslef spanc into multi rows:\npro buildUser(email, username: str): user = { user1: user = { email = \u0026quot;[email protected]\u0026quot;, username = \u0026quot;someusername123\u0026quot;, active = true, sign_in_count = 1, } } Nesting Records can be nested by creating a record type using other record types as the type for the fields of record. Nesting one record within another can be a useful way to model more complex structures:\nvar empl1: employee = { FirstName = \u0026quot;Mark\u0026quot;, LastName = \u0026quot;Jones\u0026quot;, Email = \u0026quot;[email protected]\u0026quot;, Age = 25, MonthlySalary = { Basic = 15000.00, Bonus = { HTA = 2100.00, RA = 5000.00, }, }, } Defauling Records can have default values in their fields too.\ntyp user: rec = { var username: str; var email: str; var sign_in_count: int[64] = 1; var active: bol = true; }; This makes possible to enforce some fields (empty ones), and leave the defaults untouched:\n@var[mut] user1: user = { email = \u0026quot;[email protected]\u0026quot;, username = \u0026quot;someusername123\u0026quot; } Limiting We can also restrict the values (with ranges) assigned to each field:\ntyp rgb: rec[] = { var r: int[8][.range(255)]; var g: int[8][.range(255)]; var b: int[8][.range(255)]; } var mint: rgb = { 153, 255, 187 } This of course can be achieve just with variable types and aliased types and sets too, but we would need to create two types:\ntyp rgb: set[int[8][.range(255)], int[8][.range(255)], int[8][.range(255)]]; var mint: rgb = { 153, 255, 187 } Methods A record may have methods associated with it. It does not inherit any methods bound to the given type, but the method set of an standard type remains unchanged.To create a method for a record, it needs to be declared as the reciever of that method, in FOL\u0026rsquo;s. Making a getter fucntion:\nfun (recieverRecord)someFunction(): str = { self.somestring; }; After declaring the record receiver, we then we have access to the record with the keyword self. A receiver is essentially just a type that can directly call the method.\ntyp user: rec = { var username: str; var email: str; var sign_in_count: int[64]; var active: bol; }; fun (user)getName(): str = { result = self.username; }; Methods have some benefits over regular routines. In the same package routines with the same name are not allowed but the same is not true for a method. One can have multiple methods with the same name given that the receivers they have are different.\nThen each instantiation of the record can access the method. Receivers allow us to write method calls in an OOP manner. That means whenever an object of some type is created that type can call the method from itself.\nvar[mut] user1: user = { email = \u0026quot;[email protected]\u0026quot;, username = \u0026quot;someusername123\u0026quot;, active = true, sign_in_count = 1 } .echo(user1.getName()); ","description":"","id":31,"section":"docs","tags":null,"title":"Structs","uri":"https://follang.github.io/docs/500_items/constructs/structs/"},{"content":"Satndard A standard is an established norm or requirement for a repeatable technical task. It is usually a formal declaration that establishes uniform technical criteria, methods, processes, and practices.\nS, what is a to be considered a standard:\n A standard specification is an explicit set of requirements for an item, object or service. It is often used to formalize the technical aspects of a procurement agreement or contract. A standard test method describes a definitive procedure that produces a test result. It may involve making a careful personal observation or conducting a highly technical measurement. A standard procedure gives a set of instructions for performing operations or functions. A standard guide is general information or options that do not require a specific course of action. A standard definition is formally established terminology. In FOL, standards are named collection of method signatures and are created by using blu type (a blueprint of a standard):\ntyp geometry: blu = { fun area(): flt[64]; fun perim(): flt[64]; }; There are three types of standards,\n protocol blu[prc] that enforce just function implementation - default layout blu[lay] that enforce just data implementation extended blu[ext], that enforces function and data implementation typ geometry: blu = { fun area(): flt[64]; fun perim(): flt[64]; }; typ geometry: blu[lay] = { var color: rgb; var size: int; }; typ geometry: blu[ext] = { fun area(): flt[64]; fun perim(): flt[64]; var color: rgb; var size: int; }; Contract A contract is a legally binding agreement that recognises and governs the rights and duties of the parties to the agreement. A contract is enforceable because it meets the requirements and approval of an higher authority. An agreement typically involves a written declaration given in exchange for something of value that binds the maker to do. Its an specific act which gives to the person to whom the declaration is made the right to expect and enforce performance. In the event of breach of contract, the higher authority will refrain the contract from acting.\nIn fol contracts are used to bind a type to a standard. If a type declares to use a standard, it is the job of the contract (compiler internally) to see the standard full-filled.\ntyp geo: blu = { fun area(): flt[64]; fun perim(): flt[64]; }; typ rect(geo): rec[] = { // this type makes a contract to use the geometry standard width: int[64]; heigh: int[64]; } Now we can make rect records or classes, we have to respect the contract. If we don\u0026rsquo;t implement the geo methods, when we instantiate a new object of type rect it will throw an error.\nvar aRectangle: rect = { width = 5, heigh = 6 } // this throws an error, we haven't fullfill the ocntract To do so, we need first to create the default rect methods from geo standard, then instantiate a new object:\nfun (rect)area(): flt[64] = { result = self.width + self.heigh } fun (rect)perim(): flt[64] = { result = 2 * self.width + 2 * self.heigh } var aRectangle: rect = { width = 5, heigh = 6 } // this from here on will work The benifit of standard is that, we can create a routine that as parameter takes a standard, thus all objects with the standard can use afterwards that routine:\ntyp geo: blu = { fun area(): flt[64]; fun perim(): flt[64]; }; typ rect(geo): rec[] = { // this type makes a contract to use the geometry standard width: int[64]; heigh: int[64]; } fun (rect)area(): flt[64] = { result = self.width + self.heigh } fun (rect)perim(): flt[64] = { result = 2 * self.width + 2 * self.heigh } typ circle(geo): rec[] = { // another type makes a contract to use the geometry standard radius: int[64]; } fun (circle)area(): flt[64] = { result = math::const.pi * self.radius ** 2 } fun (circle)perim(): flt[64] = { result = 2 * math::const.pi * self.radius} typ square: rec[] = { // this type does not make contract with `geo` heigh: int[64] } pro measure( shape: geo) { .echo(shape.area() + \u0026quot;m2\u0026quot;) } // a siple method to print the standard's area // instantiate two objects var aRectangle: rect = { width = 5, heigh = 6 } // creating a new rectangle var aCircle: circle = { radius = 5 } // creating a new rectangle var aSquare: square = { heigh = 6 } // creating a new square // to call the measure function that rpints the surface measure(aRectangle) // this prints: 30m2 measure(aSquare) // this throws error, square cant use measure method measure(aCircle) // this prints: 78m2 ","description":"","id":32,"section":"docs","tags":null,"title":"Standards","uri":"https://follang.github.io/docs/500_items/standards/"},{"content":"Types Generic functions - lifting The generic programming process focuses on finding commonality among similar implementations of the same algorithm, then providing suitable abstractions so that a single, generic algorithm can cover many concrete implementations. This process, called lifting, is repeated until the generic algorithm has reached a suitable level of abstraction, where it provides maximal reusability while still yielding efficient, concrete implementations. The abstractions themselves are expressed as requirements on the parameters to the generic algorithm.\npro max[T: gen](a, b: T): T = { result = a | a \u0026lt; b | b; }; fun biggerFloat(a, b: flt[32]): flt[32] = { max(a, b) } fun biggerInteger(a, b: int[64]): int[64] = { max(a, b) } Generic types - concepts Once many algorithms within a given problem domain have been lifted, we start to see patterns among the requirements. It is common for the same set of requirements to be required by several different algorithms. When this occurs, each set of requirements is bundled into a concept. A concept contains a set of requirements that describe a family of abstractions, typically data types. Examples of concepts include Input Iterator, Graph, and Equality Comparable. When the generic programming process is carefully followed, the concepts that emerge tend to describe the abstractions within the problem domain in some logical way.\ntyp container[T: gen, N: int](): obj = { var anarray: arr[T,N]; +fun getsize(): num = { result = N; } }; var aContainer: container[int, 5] = { anarray = { 1, 2, 3, 4, 5 }; }; Dispach Static dispatch (or early binding) happens when compiler knows at compile time which function body will be executed when I call a method. In contrast, dynamic dispatch (or run-time dispatch or virtual method call or late binding) happens when compiler defers that decision to run time. This runtime dispatch requires either an indirect call through a function pointer, or a name-based method lookup.\nstd foo: pro = { fun bar(); } typ[ext] int, str: int, str; fun (int)bar() = { } fun (str)bar() = { } pro callBar(T: foo)(value: T) = { value.bar() } // dispatch with generics pro barCall( value: foo ) = { value.bar() } // dispatch with standards pro main: int = { callBar(2); callBar(\u0026quot;go\u0026quot;); barCall(2); barCall(\u0026quot;go\u0026quot;) } ","description":"","id":33,"section":"docs","tags":null,"title":"Generics","uri":"https://follang.github.io/docs/500_items/generics/"},{"content":"panic keyword allows a program to terminate immediately and provide feedback to the caller of the program. It should be used when a program reaches an unrecoverable state. This most commonly occurs when a bug of some kind has been detected and it’s not clear to the programmer how to handle the error.\npro main(): int = { panic \u0026quot;Hello\u0026quot;; .echo(\u0026quot;End of main\u0026quot;); //unreachable statement } In the above example, the program will terminate immediately when it encounters the panic keyword.\nOutput:\nmain.fol:3 routine 'main' panicked at 'Hello' ------- Trying to acces an out of bound element of array:\npro main(): int = { var a: arr[int, 3] = [10,20,30]; a[10]; //invokes a panic since index 10 cannot be reached } Output:\nmain.fol:4 routine 'main' panicked at 'index out of bounds: the len is 3 but the index is 10' ------- a[10]; ^-------- index out of bounds: the len is 3 but the index is 10 A program can invoke panic if business rules are violated, for example: if the value assigned to the variable is odd it throws an error:\npro main(): int = { var no = 13; //try with odd and even if (no % 2 == 0) { .echo(\u0026quot;Thank you , number is even\u0026quot;); } else { panic \u0026quot;NOT_AN_EVEN\u0026quot;; } .echo(\u0026quot;End of main\u0026quot;); } Output:\nmain.fol:9 routine 'main' panicked at 'NOT_AN_EVEN' ------- ","description":"","id":35,"section":"docs","tags":null,"title":"Braking","uri":"https://follang.github.io/docs/650_erroe/braking/"},{"content":"Fol has many build-in functions and macros offered by compiler, and you access them by . (with space/newline/bracket before):\nvar contPoint: ptr[int] = 10;\t// make a pointer and asign the memory to value of 10 .print(.pointer_value(contPoint));\t// print the dereferenced value of pointer .echo() - print on screen\n.not() - negate\n.cast() - type casting\n.as() - type casting\n.eq() - check for equality\n.nq() - check for inequality\n.gt() - greater than\n.lt() - less than\n.ge() - greater or equal\n.le() - less or equal\n.de_alloc() - drop variable from scope\n.give_back() - return ownership\n.size_of() - variable type size\n.addres_of() - pointer address\n.pointer_value() - value of the pointer\n ","description":"","id":36,"section":"docs","tags":null,"title":"Build-In","uri":"https://follang.github.io/docs/300_meta/buildin/"},{"content":"Eventuals describe an object that acts as a proxy for a result that is initially unknown, usually because the computation of its value is not yet complete.\nAsync/Await Async methods are intended to be non-blocking operations. An await expression in an async routine doesn’t block the current thread while the awaited task is running. Instead, the expression signs up the rest of the routine as a continuation and returns control to the caller of the async routine and it means “Once this is done, execute this function”. It’s basically a “when done” hook for your code, and what is happening here is an async routine, when executed, returns a coroutine which can then be awaited. This is done usually in one thread, but can be done in multiple threads too, but thread invocations are invisible to the programmer in this case.\npro main(): int = { doItFast() | async // compiler knows that this routine has an await routine, thus continue when await rises .echo(\u0026quot;dosomething to echo\u0026quot;) // the main program does not exit until the await is resolved } fun doItFast(): str = { result = client.get(address).send() | await // this tells the routine that it might take time .echo(result) } ","description":"","id":38,"section":"docs","tags":null,"title":"Eventuals","uri":"https://follang.github.io/docs/900_processor/eventuals/"},{"content":"Fol has a number of restricted groups of keywords:\nBK (build-in keywords) BK_OR or\nBK_XOR xor\nBK_AND and\nBK_IF if\nBK_FOR for\nBK_WHEN when\nBK_EACH each\nBK_LOOP loop\nBK_IS is\nBK_HAS has\nBK_IN in\nBK_THIS this\nBK_SELF self\nBK_BREAK break\nBK_RETURN return\nBK_YEILD yeild\nBK_PANIC panic\nBK_REPORT report\nBK_CHECK check\nBK_ASSERT assert\nBK_WHERE where\nBK_TRUE true\nBK_FALSE false\nBK_AS as\nBK_CAST cast\nBK_DO do\nBK_GO go\n BUILD-IN KEYWORDS - BK:\n(BK_AS|BK_IN|...)\n AK (assignment keywords) AK_USE use\nAK_DEF def\nAK_VAR var\nAK_FUN fun\nAK_PRO pro\nAK_LOG log\nAK_TYP typ\nAK_STD std\n ASSIGNMENT KEYWORDS - AK:\n(AK_USE|AK_DEF|...)\n TK (type keywords) TK_INT int\nTK_FLT flt\nTK_CHR chr\nTK_BOL bol\nTK_ARR arr\nTTKVEC vec\nTK_SEQ seq\nTK_MAT mat\nTK_SET set\nTK_MAP map\nTK_STR str\nTK_NUM num\nTK_OPT opt\nTK_MUL mul\nTK_ANY any\nTK_PTR ptr\nTK_ERR err\nTK_NON non\nTK_REC rec\nTK_LST lst\nTK_ENM enm\nTK_UNI uni\nTK_CLS cls\nTK_STD std\nTK_MOD mod\nTK_BLK blk\n TYPE KEYWORDS - TK:\n(TK_INT|TK_FLT|...)\n Note that all of the type keywords are of three characters long. It is recomanded that new identifiers not to be of the same number of characters, as one day in the future that same identifier can be used s a keyword in FOL compiler.\n OK (option keywords) OK_PUB pub\nOK_EXP exp\n OPTION KEYWORDS - OK:\n((OK_PUB|OK_EXP|...),?)*\n Assigning (WS)*(\\W)?(AK)(\\[(OK)?\\])?\n(WS)*(AK)\n| (WS)*\\W(AK)\n| (WS)*(AK)(\\[\\])\n| (WS)*\\W(AK)(\\[\\])\n| (WS)*(AK)(\\[(OK)\\])\n| (WS)*\\W(AK)(\\[(OK)\\])\n ","description":"","id":39,"section":"docs","tags":null,"title":"Keywords","uri":"https://follang.github.io/docs/100_lexical/keywords/"},{"content":"Ordinal types\nOrdinal types have the following characteristics:\n Ordinal types are countable and ordered. This property allows the operation of functions as inc, ord, dec on ordinal types to be defined. Ordinal values have a smallest possible value. Trying to count further down than the smallest value gives a checked runtime or static error. Ordinal values have a largest possible value. Trying to count further than the largest value gives a checked runtime or static error. Ordinal types are the most primitive type of data:\n Intigers: int[options] Floating: flt[options] Characters: chr[options] Booleans: bol Intiger type An integer is a number without a fractional component. We used one integer of the u32 type, the type declaration indicates that the value it’s associated with should be an unsigned integer (signed integer types start with i, instead of u) that takes up 32 bits of space:\nvar aVar: int[u32] = 45; Each variant can be either signed or unsigned and has an explicit size. Signed and unsigned refer to whether it’s possible for the number to be negative or positive—in other words, whether the number needs to have a sign with it (signed) or whether it will only ever be positive and can therefore be represented without a sign (unsigned). It’s like writing numbers on paper: when the sign matters, a number is shown with a plus sign or a minus sign; however, when it’s safe to assume the number is positive, it’s shown with no sign.\nLength | Signed | Unsigned | ----------------------------------- 8-bit | 8 | u8 | 16-bit | 16 |\tu16 | 32-bit\t| 32 |\tu32 | 64-bit\t| 64\t| u64 | 128-bit\t| 128 |\tu128 | arch\t| arch |\tuarch | Float type Fol also has two primitive types for floating-point numbers, which are numbers with decimal points. Fol’s floating-point types are flt[32] and flt[64], which are 32 bits and 64 bits in size, respectively. The default type is flt[64] because on modern CPUs it’s roughly the same speed as flt[32] but is capable of more precision.\nLength | Type | -------------------- 32-bit\t| 32 | 64-bit\t| 64 | arch\t| arch | Floating-point numbers are represented according to the IEEE-754 standard. The flt[32] type is a single-precision float, and flt[f64] has double precision.\npro[] main: int = { var aVar: flt = 2.; // float 64 bit var bVar: flt[64] = .3; // float 64 bit .assert(.sizeof(aVar) == .sizeof(bVar)) // this will true var bVar: flt[32] = .54; // float 32 bit } Character type In The Unicode Standard 8.0, Section 4.5 \u0026ldquo;General Category\u0026rdquo; defines a set of character categories. Fol treats all characters in any of the letter as Unicode letters, and those in the Number category as Unicode digits.\nchr[utf8,utf16,utf32] def testChars: tst[\u0026quot;some testing on chars\u0026quot;] = { var bytes = \u0026quot;hello\u0026quot;; .assert(.typeof(bytes) == *var [5:0]u8); .assert(bytes.len == 5); .assert(bytes[1] == \u0026quot;e\u0026quot;); .assert(bytes[5] == 0); .assert(\u0026quot;e\u0026quot; == \u0026quot;\\x65\u0026quot;); .assert(\u0026quot;\\u{1f4a9}\u0026quot; == 128169); .assert(\u0026quot;💯\u0026quot; == 128175); .assert(.mem.eql(u8, \u0026quot;hello\u0026quot;, \u0026quot;h\\x65llo\u0026quot;)); } Boolean type The boolean type is named bol in Fol and can be one of the two pre-defined values true and false.\nbol ","description":"","id":40,"section":"docs","tags":null,"title":"Ordinal","uri":"https://follang.github.io/docs/400_type/ordinal/"},{"content":"Much like C++ and Rust, in Fol every variable declared, by default is created in stack unless explicitly specified othervise. Using option [new] or [@] in a variable, it allocates memory in the heap. The size of the allocation is defined by the type. Internally this creates a pointer to heap address, and dereferences it to the type you are having. Usually those behind the scene pointers here are unique pointers. This means that when the scope ends, the memory that the pointer used is freed.\nvar[new] intOnHeap: int[64]; @var intOnHeap: int[64]; Assignments As discussed before, declaring a new variable is like this:\nvar[pub] aVar: int[32] = 64 However, when new variable is created and uses an old variable as value, the value is always cloned for \u0026ldquo;stack\u0026rdquo; declared values, but moved for \u0026ldquo;heap\u0026rdquo; declared values.\n @var aVar: int[32] = 64 { var bVar = aVar // this moves the content from $aVar to $bVar } .echo(aVar) // this will throw n error, since the $aVar is not anymore owner of any value When the variable is moved, the owner is changed. In example above, the value 64 (saved in stack) is owned my aVar and then the ownership is moved to bVar. Now bVar is the new owner of the variable, making the aVar useless and can\u0026rsquo;t be refered anymore. Since the bVar now controls the value, it\u0026rsquo;s lifetime lasts until the end of the scope. When the scope ends, the variable is destroyed with .de_alloc() function. This because when the ovnership is moved, the attributes are moved too, so the @ of aVar is now part of the bVar even if not implicitly specified. To avoid destruction, the bVar needs to return the ownership back to aVar before the scope ends with .give_back(bVar) or !bVar.\n@var aVar: int[32] = 64 { var bVar = aVar // this moves the content from $aVar to $bVar !bvar // return ownership } .echo(aVar) // this now will print 64 This can be done automatically by using borrowing.\nBorrowing Borrowing does as the name says, it borrows a value from another variable, and at the end of the scope it automatically returns to the owner.\npro[] main: int = { var[~] aVar: int = 55; { var[bor] newVar: int = aVar // represents borrowing .echo(newVar) // this return 55 } .echo(aVar) // here $aVar it not accesible, as the ownership returns at the end of the scope .echo(newVar) // we cant access the variable because the scope has ended } Borrowing uses a predefined option [bor], which is not conventional like other languages that use \u0026amp; or *. This because you can get away just with \u0026ldquo;borrowing\u0026rdquo; without using pointers (so, symbols like * and \u0026amp; are strictly related to pointers)\nHowever, while the value is being borrowed, we can\u0026rsquo;t use the old variable while is being borrowed but we still can lend to another variable:\npro[] main: int = { var[~] aVar: int = 55; { var[bor] newVar = aVar // represents borrowing .echo(newVar) // this prints 55 .echo(aVar) // this throws an error, cos we already have borrowd the value from $aVar var[bor] anotherVar = aVar // $anotherVar again borrows from a $aVar } } When borrowed, a the value is read-only (it\u0026rsquo;s immutable). To make it muttable, firtsly, the owner needs to be muttable, secondly the borrower needs to declarare that it intends to change.\n To do so, the borrower uses var[mut, bor]. However, when the value is declared mutable by owner, only one borrower within one scope can declare to modify it:\npro[] main: int = { var[~] aVar: int = 55; { var[mut, bor] newVar = aVar // [mut, bor] represents a mutable borrowing var[mut, bor] anotherVar = aVar // this throws an error, cos we already have borrowed the muttable value before } { var[mut, bor] anotherVar = aVar // this is okay, s it is in another scope } } ","description":"","id":41,"section":"docs","tags":null,"title":"Ownership","uri":"https://follang.github.io/docs/800_memory/ownership/"},{"content":"Single letter identifiers (SILENTs) identifiers are a form of languages sugar assignment.\nLetter Lowercase Many times is needed to use a variable in-place and to decluter the code we use silents:\neach(var x: int; x in {.. 10}){ // implementation } each(x in {.. 10}){ // we use the sicale `x` here // implementation } Uppercase If a silent is uppercase, then it is a constant, can\u0026rsquo;t be changed. This is very important when using FOL for logic programming:\nlog vertical(l: line): bol = { l[A:B] and // we assign sicales `A` and `B` A[X:Y] and // we assign sicales `X` and `Y` B[X:Y2] // here we assign only `Y2` becase `X` exists from before } Symbols Meh Meh is the _ identifier. The use of the term \u0026ldquo;meh\u0026rdquo; shows that the user is apathetic, uninterested, or indifferent to the question or subject at hand. It is occasionally used as an adjective, meaning something is mediocre or unremarkable.\nWe use meh when we want to discard the variable, or we dont intend to use:\nvar array: arr[int, 3] = {1, 2, 3}; var a, _, b: int = array; // we discard, the middle value ","description":"","id":42,"section":"docs","tags":null,"title":"Silents","uri":"https://follang.github.io/docs/700_sugar/silents/"},{"content":"In fol, every calcultaion, needs to be enclosed in rounded brackets ( //to evaluate ) - except in one line evaluating, the curly brackets are allowed too { // to evaluate }:\nfun adder(a, b: int): int = { retun a + b // this will throw an error } fun adder(a, b: int): int = { retun (a + b) // this is the right way to enclose } Order of evaluation is strictly left-to-right, inside-out as it is typical for most others imperative programming languages:\n.echo((12 / 4 / 8)) // 0.375 (12 / 4 = 3.0, then 3 / 8 = 0.375) .echo((12 / (4 / 8))) // 24 (4 / 8 = 0.5, then 12 / 0.5 = 24) Calculation expressions include:\n arithmetics comparison logical compounds Arithmetics The behavior of arithmetic operators is only on intiger and floating point primitive types. For other types, there need to be operator overloading implemented.\n symbol description - substraction * multiplication + addition / division % reminder ^ exponent assert((3 + 6), 9); assert((5.5 - 1.25), 4.25); assert((-5 * 14), -70); assert((14 / 3), 4); assert((100 % 7), 2); Comparisons Comparison operators are also defined both for primitive types and many type in the standard library. Parentheses are required when chaining comparison operators. For example, the expression a == b == c is invalid and may be written as ((a == b) == c).\n Symbol Meaning == equal != not equal \u0026gt;\u0026gt; greater than \u0026lt;\u0026lt; Less than \u0026gt;= greater than or equal to \u0026lt;= Less than or equal to assert((123 == 123)); assert((23 != -12)); assert((12.5 \u0026gt;\u0026gt; 12.2)); assert(({1, 2, 3} \u0026lt;\u0026lt; {1, 3, 4})); assert(('A' \u0026lt;= 'B')); assert((\u0026quot;World\u0026quot; \u0026gt;= \u0026quot;Hello\u0026quot;)); Logical A branch of algebra in which all operations are either true or false, thus operates only on booleans, and all relationships between the operations can be expressed with logical operators such as:\n and (conjunction), denoted (x and y), satisfies (x and y) = 1 if x = y = 1, and (x and y) = 0 otherwise. or (disjunction), denoted (x or y), satisfies (x or y) = 0 if x = y = 0, and (x or) = 1 otherwise. not (negation), denoted (not x), satisfies (not x) = 0 if x = 1 and (not x) = 1ifx = 0`. assert((true and false), (false and true)); assert((true or false), true) assert((not true), false) Compounds There are further assignment operators that can be used to modify the value of an existing variable. These are the compounds or aka compound assignments. A compound assignment operator is used to simplify the coding of some expressions. For example, using the operators described earlier we can increase a variable\u0026rsquo;s value by ten using the following code:\nvalue = value + 10; This statement has an equivalent using the compound assignment operator for addition (+=).\nvalue += 10; There are compound assignment operators for each of the six binary arithmetic operators: +, -, *, /, % and ^. Each is constructed using the arithmetic operator followed by the assignment operator. The following code gives examples for addition +=, subtraction -=, multiplication *=, division /= and modulus %=:\n var value: int = 10; (value += 10); // value = 20 (value -= 5); // value = 15 (value *= 10); // value = 150 (value /= 3); // value = 50 (value %= 8); // value = 2 Compound assignment operators provide two benefits. Firstly, they produce more compact code; they are often called shorthand operators for this reason. Secondly, the variable being operated upon, or operand, will only be evaluated once in the compiled application. This can make the code more efficient.\n","description":"","id":43,"section":"docs","tags":null,"title":"Calculations","uri":"https://follang.github.io/docs/200_expressions/300_exp/arithmetics/"},{"content":"Containers are of compound types. They contain other primitive or constructed types. To access the types in container those brackets are used: [], so:\nvar container: type = { element, element, element } // declaring a container var varable: type = container[2] // accessing the last element Containers are always zero indexed\n Static Arrays arr[type,size] Arrays are the most simple type of container. They contain homogeneous type, meaning that each element in the array has the same type. Arrays always have a fixed length specified as a constant expression arr[type, size]. They can be indexed by any ordinal type to acces its members.\npro[] main: int = { var anArray: arr[int, 5] = { 0, 1, 2, 3, 4 }; // declare an array of intigers of five elements var element = anArray[3]; // accessing the element .echo(element) // prints: 3 } To allocate memory on heap, the var[new] is used more about memory, ownreship and pointer :\npro[] main: int = { var[new] aSequence: arr[str, 3] = { \u0026quot;get\u0026quot;, \u0026quot;over\u0026quot;, \u0026quot;it\u0026quot; }; // this array is stored in stack } Dynamic arrays Dynamic are similar to arrays but of dynamic length which may change during runtime (like strings). A dynamic array s is always indexed by integers from 0 to .len(s)-1 and its bounds are checked.\nThe lower bound of an array or sequence may be received by the built-in .low(), the higher bound by .high(). The length may be received by .len().\nDynamic arrays are a dynamically allocated (hence the name), thus if not allocated in heap but in stack, the size will be defined automatically in compile time and will be changed to static array.\n There are two implementations of dynamic arrays:\n vectors vec[] sequences seq[] Vecotors Vectors are dynamic arrays, that resizes itself up or down depending on the number of content.\nAdvantage:\n accessing and assignment by index is very fast O(1) process, since internally index access is just [address of first member] + [offset]. appending object (inserting at the end of array) is relatively fast amortized O(1). Same performance characteristic as removing objects at the end of the array. Note: appending and removing objects near the end of array is also known as push and pop. Disadvantage:\n inserting or removing objects in a random position in a dynamic array is very slow O(n/2), as it must shift (on average) half of the array every time. Especially poor is insertion and removal near the start of the array, as it must copy the whole array. Unpredictable performance when insertion or removal requires resizing There is a bit of unused space, since dynamic array implementation usually allocates more memory than necessary (since resize is a very slow operation) In FOL vecotrs are represented like this:\nvec[type] Example:\npro[] main: int = { var[new] aVEctor: vec[str] = { \u0026quot;get\u0026quot;, \u0026quot;over\u0026quot;, \u0026quot;it\u0026quot; }; // declare an array of intigers of five elements var element = aVEctor[3]; // accessing the element } Sequences Sequences are linked list, that have a general structure of [head, [tail]], head is the data, and tail is another Linked List. There are many versions of linked list: singular, double, circular etc\u0026hellip;\nAdvantage:\n fast O(1) insertion and removal at any position in the list, as insertion in linked list is only breaking the list, inserting, and repairing it back together (no need to copy the tails) linked list is a persistent data structure, rather hard to explain in short sentence, see: wiki-link . This advantage allow tail sharing between two linked list. Tail sharing makes it easy to use linked list as copy-on-write data structure. Disadvantage:\n Slow O(n) index access (random access), since accessing linked list by index means you have to recursively loop over the list. poor locality, the memory used for linked list is scattered around in a mess. In contrast with, arrays which uses a contiguous addresses in memory. Arrays (slightly) benefits from processor caching since they are all near each other In FOL sequneces are represented like this:\nseq[type] Example:\npro[] main: int = { var[new] aSequence: seq[str] = { \u0026quot;get\u0026quot;, \u0026quot;over\u0026quot;, \u0026quot;it\u0026quot; }; // declare an array of intigers of five elements var element = aSequence[3]; // accessing the element } SIMD Matrixes are of type SIMD (single instruction, multiple data )\nMatrix mat[sizex] mat[sizex,sizey] mat[sizex,sizey,sizez] Sets set[type,type,type..] A set is a general way of grouping together a number of values with a variety of types into one compound type. Sets have a fixed length: once declared, they cannot grow or shrink in size. In other programming languages they usually are referenced as tuples.\npro[] main: int = { var aSet: set[str, flt, arr[int, 2]] = { \u0026quot;go\u0026quot;, .3, { 0, 5, 3 } }; var element = aSet[2][1]; // accessing the [1] element of the `arr` in the set .echo(element) // prints: 5 } Maps map[key,value] A map is an unordered group of elements of one type, called the element type, indexed by a set of unique keys of another type, called the key type.\npro[] main: int = { var aMap: map[str, int] = { {\u0026quot;US\u0026quot;,45}, {\u0026quot;DE\u0026quot;,82}, {\u0026quot;AL\u0026quot;,54} }; var element = aMap[\u0026quot;US\u0026quot;]; // accessing the \u0026quot;US\u0026quot; key .echo(element) // prints: 45 } The number of map elements is called its length. For a map aMap, it can be discovered using the built-in function .len and may change during execution To add a new element, we use name+[element] or addfunction:\n.echo(.len(aMap)) // prints: 3 aMap.add( {\u0026quot;IT\u0026quot;,55} ) aMap+[{\u0026quot;RU\u0026quot;,24}] .echo(.len(aMap)) // prints: 4 The comparison operators == and != must be fully defined for operands of the key type; thus the key type must not be a function, map, or sequence.\nMaps are a growable containers too, thus if not allocated in heap but in stack, the size will be defined automatically in compile time and will be changet to static containers\n Axiom axi[typ, typ] A axiom is a list of facts. A fact is a predicate expression that makes a declarative statement about the problem domain. And whenever a variable occurs in a expression, it is assumed to be universally quantified as silent.\nvar likes: axi[str, str] = { {\u0026quot;bob\u0026quot;,\u0026quot;alice\u0026quot;} , {\u0026quot;alice\u0026quot;,\u0026quot;bob\u0026quot;}, {\u0026quot;dan\u0026quot;,\u0026quot;sally\u0026quot;} }; Accesing any container always returns the value, but if we put an : before the access symbol so :[], then it will return true or false if there is data or not on the specified access.\n likes[\u0026quot;bob\u0026quot;,\u0026quot;alice\u0026quot;] // will return {\u0026quot;bob\u0026quot;,\u0026quot;alice\u0026quot;} likes:[\u0026quot;bob\u0026quot;,\u0026quot;alice\u0026quot;] // will return true likes[\u0026quot;sally\u0026quot;,\u0026quot;dan\u0026quot;] // will return {} likes:[\u0026quot;sally\u0026quot;,\u0026quot;dan\u0026quot;] // will return false Axioms are a data types that are meant to be used with logic programming. There are containers where facts are stated, and when we want to acces the data, they are always served as containers.\nvar parent: axi[str, str] = { {\u0026quot;albert\u0026quot;,\u0026quot;bob\u0026quot;}, {\u0026quot;alice\u0026quot;,\u0026quot;bob\u0026quot;}, {\u0026quot;bob\u0026quot;,\u0026quot;carl\u0026quot;}, {\u0026quot;bob\u0026quot;,\u0026quot;tom\u0026quot;} }; parent[\u0026quot;bob\u0026quot;,*] // this gets all elements that \u0026quot;bob\u0026quot; relates to {\u0026quot;carl\u0026quot;, \u0026quot;tom\u0026quot;} parent[*,\u0026quot;bob\u0026quot;] // this gets all elements that \u0026quot;bob\u0026quot; relates from {\u0026quot;albert\u0026quot;, \u0026quot;alice\u0026quot;} Adding new element can be done like in other containers:\nvar parent: axi[str, str] = { {\u0026quot;albert\u0026quot;,\u0026quot;bob\u0026quot;}, {\u0026quot;alice\u0026quot;,\u0026quot;bob\u0026quot;}, {\u0026quot;bob\u0026quot;,\u0026quot;carl\u0026quot;}, {\u0026quot;bob\u0026quot;,\u0026quot;tom\u0026quot;} }; parent.add({\u0026quot;albert\u0026quot;,\u0026quot;betty\u0026quot;}) parent.add({\u0026quot;albert\u0026quot;,\u0026quot;bill\u0026quot;}) parent.add({\u0026quot;alice\u0026quot;,\u0026quot;betty\u0026quot;}) parent.add({\u0026quot;alice\u0026quot;,\u0026quot;bill\u0026quot;}) And they can be nesetd too:\nvar line: axi[axi[int, int], axi[int, int]] = {{{4,5},{4,8}},{{8,5},{4,5}}} And we can use the simplified form too, just axi instead of all the type. We let the compiler fill in the for us:\nvar line: axi = {{{4,5},{4,8}},{{8,5},{4,5}}} ","description":"","id":45,"section":"docs","tags":null,"title":"Container","uri":"https://follang.github.io/docs/400_type/container/"},{"content":"A coroutine is a task given form the main thread, similar to a routine, that can be in concurrent execution with other tasks of the same program though other routines. A worker takes the task and runs it, concurrently. Each task in a program can be assigned to one or multiple workers.\nThree characteristics of coroutine distinguish them from normal routines:\n First, a task may be implicitly started, whereas a routine must be explicitly called. Second, when a program unit invokes a task, in some cases it need not wait for the task to complete its execution before continuing its own. Third, when the execution of a task is completed, control may or may not return to the unit that started that execution. Fourth and most importantly, the execution of the routine is entirely independent from main thread. In fol to assign a task to a worker, we use the symbols [\u0026gt;]\nChannels FOL provides asynchronous channels for communication between threads. Channels allow a unidirectional flow of information between two end-points: the Transmitter and the Receiver. It creates a new asynchronous channel, returning the tx/tx halves. All data sent on the Tx (transmitter) will become available on the Rx (receiver) in the same order as it was sent. The data is sent in a sequence of a specifies type seq[type]. tx will not block the calling thread while rx will block until a message is available.\npro main(): int = { var channel: chn[str]; for (0 ... 4) { [\u0026gt;]doItFast() | channel[tx] // sending the output of four routines to a channel transmitter // each transmitter at the end sends the close signal } var fromCh1 = channel[rx][0] // reciveing data from one transmitter, `0` } fun doItFast(i: int; found: bol): str = { return \u0026quot;hello\u0026quot; } If we want to use the channel within the function, we have to clone the channel\u0026rsquo;s tx and capture with an ananymus routine: Once the channels transmitter goes out of scope, it gets disconnected too.\npro main(): int = { var channel: chn[str]; // a channel with four buffer transmitters var sequence: seq[str]; for (0 ... 4) { [\u0026gt;]fun()[channel[tx]] = { // capturin gthe pipe tx from four coroutines for(0 ... 4){ \u0026quot;hello\u0026quot; | channel[tx] // the result are sent fom withing the funciton eight times } } // when out of scope a signal to close the `tx` is sent } select(channel as c){ sequence.push(channel[rx][c]) // select statement will check for errors and check which routine is sending data } } Locks - Mutex Mutex is a locking mechanism that makes sure only one task can acquire the mutexed varaible at a time and enter the critical section. This task only releases the mutex when it exits the critical section. It is a mutual exclusion object that synchronizes access to a resource.\nIn FOL mutexes can be passed only through a routine. When declaring a routine, instead of using the borrow form with ( // borrowing variable ), we use double brackets (( // mutex )). When we expect a mutex, then that variable, in turn has two method more:\n the lock() which unwraps the variable from mutex and locks it for writing and the unlock() which releases the lock and makes the file avaliable to other tasks fun loadMesh(path: str, ((meshes)): vec[mesh]) = { // declaring a *mutex and *atomic reference counter with double \u0026quot;(( //declaration ))\u0026quot; var aMesh: mesh = mesh.loadMesh(path) meshes.lock() meshes.push(aMesh) // there is no need to unlock(), FOL automatically drops at the end of funciton // if the function is longer, then we can unlock to not keep other tasks waiting } pro main(): int = { ~var meshPath: vec[str]; ~var meshes: vec[mesh]; var aFile = file.readfile(filepath) || .panic(\u0026quot;cant open the file\u0026quot;) each( line in aFile.line() ) { meshPath.push(line) }; for(m in meshPath) { [\u0026gt;]loadMesh(m, meshes) }; } ","description":"","id":46,"section":"docs","tags":null,"title":"Corutines","uri":"https://follang.github.io/docs/900_processor/corutines/"},{"content":"Encoding Identifiers in FOL can be any string of letters, digits and underscores, but beginning with a letter. Two immediate following underscores __ are not allowed.\nIDENTIFIER:\n[a-z A-Z] [a-z A-Z 0-9 _]* | _ [a-z A-Z 0-9 _]+\n An identifier is any nonempty ASCII string of the following form:\nEither\n The first character is a letter. The remaining characters are alphanumeric or _. Or\n The first character is _. The identifier is more than one character. _ alone is not an identifier. The remaining characters are alphanumeric or _. Identifier equality Two identifiers are considered equal if the following algorithm returns true:\npro sameIdentifier(a, b: string): bol = { result = a.replace(\u0026quot;_\u0026quot;, \u0026quot;\u0026quot;).toLowerAscii == b.replace(\u0026quot;_\u0026quot;, \u0026quot;\u0026quot;).toLowerAscii } That means all letters are compared case insensitively within the ASCII range and underscores are ignored. This rather unorthodox way to do identifier comparisons is called partial case insensitivity and has some advantages over the conventional case sensitivity: It allows programmers to mostly use their own preferred spelling style, be it humpStyle or snake_style, and libraries written by different programmers cannot use incompatible conventions\n","description":"","id":47,"section":"docs","tags":null,"title":"Identifiers","uri":"https://follang.github.io/docs/100_lexical/identify/"},{"content":"Are a very complicated system, and yet can be used as simply as in-place replacement. A lot of build-in macros exist in the language to make the code more easy to type. Below are some system defined macros.\nFor example, wherever $ is before any variable name, its replaced with .to_string. Or wherever ! is before bol name, its replaced with .not but when the same ! is placed before ptr it is replaced with .delete_pointer.\ndef '$'(a: any): mac = '.to_string' def '!'(a: bol): mac = '.not ' def '!'(a: ptr): mac = '.delete_pointer'; def '*'(a: ptr): mac = '.pointer_value'; def '#'(a: any): mac = '.borrow_from'; def '\u0026amp;'(a: any): mac = '.address_of'; ","description":"","id":48,"section":"docs","tags":null,"title":"Macors","uri":"https://follang.github.io/docs/300_meta/macros/"},{"content":"Piping is a process that connects the output of the expression to the left to the input of the expression of the right. You can think of it as a dedicated program that takes care of copying everything that one expressionm prints, and feeding it to the next expression. The idea is the same as bash pipes. For example, an routine output is piped to a conditional through pipe symbol | then the conditional takes the input and returns true or false. If returned false, then the second part of pipe is returned. To access the piped variable, this keyword is used:\npro[] main: int = { fun addFunc(x, y: int): int = { return x + y; } var aVar: int = addFunc(4, 5) | if(this \u0026gt; 8) | return 6; } However, when we assign an output of a function to a variable, we shoud expect that errors within funciton can happen. By default, everytime a function is called, and the function throws an error in will be reported up.\nvar aVar: int = addFunc(4, 5); // if there are errors, and the call is in main function, the program will exit // because is the last concatinator of the 'report' error However, when we use pipes, we pass the function values (result and the error) to the next expression, and then, it is the second expression\u0026rsquo;s responsibility to deal with it. We use the built-in check that checks for error on the function:\nvar aVar: int = addFunc(4, 5) | check(this) | return 5; // if there are errors, the error is passed to the next sepression with pipe // here, if there is errors, will be checked and the default value of 5 will return There is a shorter way to do this kind of error checking. For that we use double pipe ||. For example, we assign the output of a function to a variable, but the function may fail, so we want a default variable:\nvar aVar: int = addFunc(4, 5) || return 5; Or to handle the error ourselves. This simply says, if i get the error, then we can panic or report with custom message:\nvar aVar: int = addFunc(4, 5) || panic \u0026quot;something bad inside function has happened\u0026quot;; More on error handling can be found here\n","description":"","id":49,"section":"docs","tags":null,"title":"Pipes","uri":"https://follang.github.io/docs/700_sugar/pipes/"},{"content":"The only way to access the same memory with different variable is by using pointers. In example below, we create a pointer, and when we want to dereference it to modify the content of the address that the pointer is pointing to, we use *ptrname or .pointer_value(ptrname).\n@var aContainer: str[] = \u0026quot;hi there\u0026quot;; //allocating memory on the heap for IMMUTABLE variable var contPoint: ptr[str[]] = aContainer; echo(*contPoint); // here we dereference it and echo \u0026quot;hi there\u0026quot; Bare in mind, that the pointer (so, the address itself) can\u0026rsquo;t be changes, unless the variable itself and pointer created are marked as var[mut].\n@var[mut] aContainer: str[] = \u0026quot;hi there\u0026quot;; //allocating memory on the heap for MUTABLE variable var[mut] contPoint: ptr[str[]] = aContainer; *contPoint = \u0026quot;hello sailor\u0026quot; // we dereference it and modify because is mutable echo(*contPoint); // here we dereference it again and echo \u0026quot;hello sailor\u0026quot; To see tha address of a pointer we use \u0026amp;ptrname or .address_of(ptrname)\nUnique pointer Ponters are very simimilar to RUST move pointer, it actually, deletes the first pointer and references the new one to the location of deleted one. However this works only when the pointer is unique (all pointers by default all unique). This is like borrowing, but does not invalidate the source variable:\nvar aContainer: arr[int, 5] = { zero, one, two, three, four }; var contPoint1: ptr[] = aContainer; var contPoint2: ptr[] = aContainer; // this throws an error, cos, we already have another pointer to that variable Shred pointer Ponter can be shared too. They can get referenced by another pointer, and they don\u0026rsquo;t get destroyed until the last reference\u0026rsquo;s scope is finished. This is exacly like smart shared_ptr in C++. Pointer to this pointer makes a reference not a copy as unique pointers. Dereferencing is a bit complicated here, as when you dereference a pointer pointer you get a pointer, so you need to dereference it too to get the value.\nvar aContainer: arr[int, 5] = { zero, one, two, three, four }; var contPoint1: ptr[shared] = aContainer; var contPoint2: ptr[shared] = aContainer; // this works, as the pointers are shared However, the risk is that, when changing one pointer, the other one is now aware of chages, and mught have unforeseen consequences.\nRaw pointer Lastly, pointers can be raw too. This is the base of ALL POINTERS AND VARIABLES. Pointers of this type need to MANUALLY GET DELETED.\nvar aContainer: arr[int, 5] = { zero, one, two, three, four }; var contPoint1: ptr[raw] = aContainer; var contPoint2: ptr[raw] = aContainer; Deleting:\n!(contPoint1) !(contPoint2) Pointer of a pointer Pointer of a pointer then is just, as layer, after layer.\n@var aContainer: arr[int, 5] = { zero, one, two, three, four }; var contPoint: ptr[] = aContainer; var pointerPoint: ptr[] = \u0026amp;contPoint; Dereferencing (step-by-step):\nvar apointerValue = *pointerPoint var lastpointerValue = *apointerValue Dereferencing (all-in-one):\nvar lastpointer = *(*pointerPoint) Raw pointer of pointers are not suggested. If a pointer gets deleted before the new pointer that points at it, we get can get memory corruptions:\nvar aContainer: arr[int, 5] = { zero, one, two, three, four }; var contPoint: ptr[raw] = aContainer; var pointerPoint: ptr[raw] = \u0026amp;contPoint; Deleting:\n!(pointerPoint) !(contPoint) ","description":"","id":50,"section":"docs","tags":null,"title":"Pointers","uri":"https://follang.github.io/docs/800_memory/pointers/"},{"content":"report can be used to handle recoverable errors. As discussed here, FOL uses two variables result nd error in return of each routine. As name implies, result represents the type of the value that will be returned in a success case, and error represents the type of the error err[] that will be returned in a failure case.\nWhen we use the keyword report, the error is returned to the routine\u0026rsquo;s error variable and the routine qutis executing (the routine, not the program).\nuse file: mod[std] = { std::fs::File } pro main(): int = { pro[] fileReader(path: str): str = { var aFile = file.readfile(path) if ( check(aFile) ) { report \u0026quot;File could not be opened\u0026quot; + file // report will not break the program, but will return the error here, and the routine will stop } else { return file.to_string() // this will be executed only if file was oopened without error } } } Form this point on, the error is concatinated up to the main function. This is known as propagating the error and gives more control to the calling code, where there might be more information or logic that dictates how the error should be handled than what you have available in the context of your code.\nuse file: mod[std] = { std::fs::File } pro main(): int = { var f = file.open(\u0026quot;main.jpg\u0026quot;); // main.jpg doesn't exist if (check(f)) { report \u0026quot;File could not be opened\u0026quot; + file // report will not break the program } else { .echo(\u0026quot;File was open sucessfulley\u0026quot;) // this will be executed only if file was oopened without error } } ","description":"","id":51,"section":"docs","tags":null,"title":"Recover","uri":"https://follang.github.io/docs/650_erroe/recover/"},{"content":"Alternatives are used when we want to simplify code. For example, define an alternative, so whenever you write +var it is the same as var[+].\ndef '+var': alt = 'var[+]' def '~var': alt = 'var[~]' def '.pointer_content': alt = '.pointer_value' ","description":"","id":52,"section":"docs","tags":null,"title":"Alternatives","uri":"https://follang.github.io/docs/300_meta/alternatives/"},{"content":"Defaults are a way to change the default behaviour of options. Example the default behaviour of str when called without options. By defalt str is it is saved on stack, it is a constant and not public, thus has str[pil,imu,nor], and we want to make it mutable and saved on heap by default:\ndef 'str': def[] = 'str[new,mut,nor]' ","description":"","id":53,"section":"docs","tags":null,"title":"Defaults","uri":"https://follang.github.io/docs/300_meta/defaults/"},{"content":"Comments in FOL code DON\u0026rsquo;T follow the traditional style of line (//) comment forms.\n Normal comments They are represented with backtick.\nSINGLE_LINE_COMMENT :\n`this is a single line comment` MULTI_LINE_COMMENT :\n`this is a multi line comment` Docs comments Doc comments have at the beggining of comment the optinon [doc].\nDOC_COMMENT:\n`[doc] this is a documentation comment` ","description":"","id":54,"section":"docs","tags":null,"title":"Comments","uri":"https://follang.github.io/docs/100_lexical/comments/"},{"content":"Strings Strings are a complex type that are made of array of chars with null terminator \u0026lsquo;\\0\u0026rsquo;, and by default is utf8 encoded:\nstr[] Number Number type is an abstraction of intiger and float type. It can be imaginary too.\nnum[] Pointer ptr[] Error err[] ","description":"","id":55,"section":"docs","tags":null,"title":"Complex","uri":"https://follang.github.io/docs/400_type/complex/"},{"content":"A literal expression consists of one or more of the numerical/letter forms described earlier. It directly describes a numbers, characters, booleans, containers and constructs.\nThere are two type of literals:\n values calls Value literals Value literals are the simpliest expressions. They are direct values assigned to variables and are divided into two types:\n singletons clusters Singelton literals Singleton literals represent one sigle values:\n4 // intiger literal 0xA8 // hex-intiger literal 4.6 // floating-point literal 5i // imaginary literal \u0026quot;c\u0026quot; // character literal \u0026quot;one\u0026quot; // string literal true // boolean literal Cluster literals Cluster literals represent both container types and construct types. Cluster literals are always enclosed within curly brackets { }. The difference between scopes and cluster literals is that cluster literals shoud always have comma , within the initializaion and assignment brackets, e.g { 5, }.\nContainers Some simple container expressions\n{ 5, 6, 7, 8, } // array, vector, sequences { \u0026quot;one\u0026quot;:1, \u0026quot;two\u0026quot;:2, } // maps { 6, } // single element container A 3x3x3 matrix\n{{{1,2,3},{4,5,6},{7,8,9}},{{1,2,3},{4,5,6},{7,8,9}},{{1,2,3},{4,5,6},{7,8,9}}} Constructs // constructs { email = \u0026quot;[email protected]\u0026quot;, username = \u0026quot;someusername123\u0026quot;, active = true, sign_in_count = 1 } // nested constructs { FirstName = \u0026quot;Mark\u0026quot;, LastName = \u0026quot;Jones\u0026quot;, Email = \u0026quot;[email protected]\u0026quot;, Age = 25, MonthlySalary = { Basic = 15000.00, Bonus = { HTA = 2100.00, RA = 5000.00, }, }, } Call literals Call literals are function calls that resolve to values:\nvar seven: int = add(2, 5); // assigning variables \u0026quot;seven\u0026quot; to function call \u0026quot;add\u0026quot; `typ Vector: rec = {\nvar x: flt\nvar y: flt\n}\ntyp Rect: rec = {\nvar pos: Vector\nvar size: Vecotr\n}\nfun make_rect(min, max: Vector): Rect {\nreturn [Rect]{{min.x, min.y}, {max.x - max.y, max.y - max.y}}\nreturn [Rect]{pos = {min.x, min.y}, size = {max.x - max.y, max.y - max.y}}\n}\n`\n","description":"","id":56,"section":"docs","tags":null,"title":"Literals","uri":"https://follang.github.io/docs/200_expressions/300_exp/literals/"},{"content":"Optional var someMixtureInt: ?int = 45; Never var someNverType: !int = panic(); ","description":"","id":57,"section":"docs","tags":null,"title":"Mixture","uri":"https://follang.github.io/docs/700_sugar/mixture/"},{"content":"Templates are supposed to be mostly used for operator overloading. They are glorified functions, hence used with pro or fun instead of def.\nFor example here is how the != is defined:\nfun '!='(a, b: int): bol = { return .not(.eq(a, b)) } .assert( 5 != 4 ) or define $ to return the string version of an object (careful, it is object$ and not $object, the latest is a macro, not a template):\npro (file)'$': str = { return \u0026quot;somestring\u0026quot; } .echo( file$ ) ","description":"","id":58,"section":"docs","tags":null,"title":"Templates","uri":"https://follang.github.io/docs/300_meta/temp/"},{"content":"Limiting is a syntactic way to set boundaries for variables. The way FOL does is by using [] right after the type declaration type[], so: type[options][limits]\nInitger limiting Example, making a intiger variable have only numbers from 0 to 255 that represents an RGB value for a single color:\nvar rgb: int[][.range(255)]; Character limiting It works with strings too, say we want a string that can should be of a particular form, for example an email:\nvar email: str[][.regex('[._a-z0-9]+@[a-z.]+')] ","description":"","id":59,"section":"docs","tags":null,"title":"Limits","uri":"https://follang.github.io/docs/700_sugar/limits/"},{"content":"There are two range expressions:\n Defined ranges Undefined ranges Defined ranges Defined ranges represent a group of values that are generated as a sequence based on some predefined rules. Ranges are represented with two dots .. operator.\n{ 1..8 } // a range from 1 to 8 { 1,2,3,4,5,6,7,8 } { 8..1 } // a range from 8 to 1 { 8,7,6,5,4,3,2,1 } { 1..8..2 } // a range from 1 to 8 jumping by 2 { 1,3,5,7 } { 3..-3 } // a range from 4 to -4 { 3,2,1,0,-1,-2,-3 } { -3..3 } // a range from -3 to 3 { -3,-2,-1,0,1,2,3 } { ..5 } // a range form 0 to 5 { 0,1,2,3,4,5 } { ..-5 } // a range from 0 to -5 { 0,-1,-2,-3,-4,-5 } { 5.. } // a range from 5 to 0 { 5,4,3,2,1,0 } { -5.. } // a range from -5 to 0 { -5,-4,-3,-2,-1,0 } syntax meaning start..end from start to end ..end from zero to end start.. from start to zero Undefined ranges Undefined ranges represent values that have only one side defined at the definition time, and the compiler defines the other side at compile time. They are represented with three dots ...\n{ 2... } // from 2 to infinity syntax meaning start... from start to infinite In most of the cases, they are used for variadic parameters passing:\nfun calc(number: ...int): int = { return number[0] + number[1] + number[2] * number[3]} ","description":"","id":60,"section":"docs","tags":null,"title":"Ranges","uri":"https://follang.github.io/docs/200_expressions/300_exp/ranges/"},{"content":"Optional Either are empty or have a value\nopt[] Never nev[] The never type is a type with no values, representing the result of computations that never complete.\nUnion Union is a data type that allows different data types to be stored in the same memory locations. Union provides an efficient way of reusing the memory location, as only one of its members can be accessed at a time. It uses a single memory location to hold more than one variables. However, only one of its members can be accessed at a time and all other members will contain garbage values. The memory required to store a union variable is the memory required for the largest element of the union.\nWe can use the unions in the following locations.\n Share a single memory location for a variable and use the same location for another variable of different data type. Use it if you want to use, for example, a long variable as two short type variables. We don’t know what type of data is to be passed to a function, and you pass union which contains all the possible data types. var aUnion: uni[int[8], int, flt]; Any any[] Null nil ","description":"","id":61,"section":"docs","tags":null,"title":"Special","uri":"https://follang.github.io/docs/400_type/special/"},{"content":"Whitespaces Whitespace is any non-empty string containing only characters that have the below Unicode properties:\n U+0009 (horizontal tab, \u0026lsquo;\\t\u0026rsquo;) U+000B (vertical tab) U+000C (form feed) U+0020 (space, ' \u0026lsquo;) U+0085 (next line) U+200E (left-to-right mark) U+200F (right-to-left mark) U+2028 (line separator) U+2029 (paragraph separator) New lines New line are used as end-of-line separators:\n U+000A (line feed, \u0026lsquo;\\n\u0026rsquo;) U+000D (carriage return, \u0026lsquo;\\r\u0026rsquo;) ","description":"","id":62,"section":"docs","tags":null,"title":"Whitespaces","uri":"https://follang.github.io/docs/100_lexical/whitespaces/"},{"content":"Variable As variable assignment:\nvar checker: str = if (variable){ in {..10} -\u0026gt; \u0026quot;in range of 1-10\u0026quot;; in {11..20} -\u0026gt; \u0026quot;in range of 11-20\u0026quot;; * -\u0026gt; \u0026quot;out of range\u0026quot;; } var is_it: int = if (variable){ is \u0026quot;one\u0026quot; -\u0026gt; 1; is \u0026quot;two\u0026quot; -\u0026gt; 2; * -\u0026gt; 0; } var has_it: bol = if (variable){ has \u0026quot;o\u0026quot;, \u0026quot;k\u0026quot; -\u0026gt; true; * -\u0026gt; false; } Function As function return:\nfun someValue(variable: int): str = if (variable){ in {..10} -\u0026gt; \u0026quot;1-10\u0026quot;; in {11..20} -\u0026gt; \u0026quot;11-20\u0026quot;; * -\u0026gt; \u0026quot;0\u0026quot;; } ","description":"","id":63,"section":"docs","tags":null,"title":"Matching","uri":"https://follang.github.io/docs/700_sugar/matching/"},{"content":"There are four access expresions:\n namespace member access routine member access container memeber access field member access Subprogram access In most programming languages, it is called \u0026ldquo;method-call expresion\u0026rdquo;. A method call consists of an expression (the receiver) followed by a single dot ., an expression path segment, and a parenthesized expression-list:\n\u0026quot;3.14\u0026quot;.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 :::\nuse 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.\nvar 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:\n 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:\n 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:\nvar 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.\nMaps Accesing maps is donw by using the key within square-bracket-enclosed:\nvar someMap: map[str, int] = { {\u0026quot;prolog\u0026quot;, 1}, {\u0026quot;lisp\u0026quot;, 2}, {\u0026quot;c\u0026quot;, 3} } someMap[\u0026quot;lisp\u0026quot;] // 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):\nvar parent: axi[str, str] = { {\u0026quot;albert\u0026quot;,\u0026quot;bob\u0026quot;}, {\u0026quot;alice\u0026quot;,\u0026quot;bob\u0026quot;}, {\u0026quot;bob\u0026quot;,\u0026quot;carl\u0026quot;}, {\u0026quot;bob\u0026quot;,\u0026quot;tom\u0026quot;} }; parent[\u0026quot;albert\u0026quot;,*] // this will return strng vector: {\u0026quot;bob\u0026quot;} parent[\u0026quot;bob\u0026quot;,*] // this will return strng vector: {\u0026quot;carl\u0026quot;,\u0026quot;tom\u0026quot;} parent[*,_] // this will match to {\u0026quot;albert\u0026quot;, \u0026quot;alice\u0026quot;, \u0026quot;bob\u0026quot;} Matching can be with a vector too:\nvar parent: axi[str, str] = { {\u0026quot;albert\u0026quot;,\u0026quot;bob\u0026quot;}, {\u0026quot;alice\u0026quot;,\u0026quot;bob\u0026quot;}, {\u0026quot;bob\u0026quot;,\u0026quot;carl\u0026quot;}, {\u0026quot;bob\u0026quot;,\u0026quot;tom\u0026quot;}, {\u0026quot;maggie\u0026quot;,\u0026quot;bill\u0026quot;} }; var aVec: vec[str] = { \u0026quot;tom\u0026quot;, \u0026quot;bob\u0026quot; }; parent[*,aVec] // will match all possible values that have \u0026quot;tom\u0026quot; ot \u0026quot;bob\u0026quot; as second element // in this case will be a strng vector: {\u0026quot;albert\u0026quot;, \u0026quot;alice\u0026quot;, \u0026quot;bob\u0026quot;} a more complex matching:\nvar class: axi; class.add({\u0026quot;cs340\u0026quot;,\u0026quot;spring\u0026quot;,{\u0026quot;tue\u0026quot;,\u0026quot;thur\u0026quot;},{12,13},\u0026quot;john\u0026quot;,\u0026quot;coor_5\u0026quot;}) class.add({\u0026quot;cs340\u0026quot;,\u0026quot;winter\u0026quot;,{\u0026quot;tue\u0026quot;,\u0026quot;fri\u0026quot;},{12,13},\u0026quot;mike\u0026quot;,\u0026quot;coor_5\u0026quot;}) class.add({\u0026quot;cs340\u0026quot;,winter,{\u0026quot;wed\u0026quot;,\u0026quot;fri\u0026quot;},{15,16},\u0026quot;bruce\u0026quot;,\u0026quot;coor_3\u0026quot;}) class.add({\u0026quot;cs101\u0026quot;,winter,{\u0026quot;mon\u0026quot;,\u0026quot;wed\u0026quot;},{10,12},\u0026quot;james\u0026quot;,\u0026quot;coor_1\u0026quot;}) class.add({\u0026quot;cs101\u0026quot;,spring,{\u0026quot;tue\u0026quot;,\u0026quot;tue\u0026quot;},{16,18},\u0026quot;tom\u0026quot;,\u0026quot;coor_1\u0026quot;}) var aClass = \u0026quot;cs340\u0026quot; class[aClass,_,[_,\u0026quot;fri\u0026quot;],_,*,_] // this will return string vector: {\u0026quot;mike\u0026quot;, bruce} // it matches everything that has aClass ad \u0026quot;fri\u0026quot; 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.\nvar 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] = { {\u0026quot;bob\u0026quot;,\u0026quot;alice\u0026quot;} , {\u0026quot;alice\u0026quot;,\u0026quot;bob\u0026quot;}, {\u0026quot;dan\u0026quot;,\u0026quot;sally\u0026quot;} }; likes[\u0026quot;bob\u0026quot;,\u0026quot;alice\u0026quot;]: // will return true likes[\u0026quot;sally\u0026quot;,\u0026quot;dan\u0026quot;]: // will return false In-Place assignment One of the features that is very important in arrays is that they can assign variables immediately:\nvar 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 =\u0026gt; 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:\nvar parent: axi[str, str] = { {\u0026quot;albert\u0026quot;,\u0026quot;bob\u0026quot;}, {\u0026quot;alice\u0026quot;,\u0026quot;bob\u0026quot;}, {\u0026quot;bob\u0026quot;,\u0026quot;carl\u0026quot;}, {\u0026quot;bob\u0026quot;,\u0026quot;tom\u0026quot;}, {\u0026quot;maggie\u0026quot;,\u0026quot;bill\u0026quot;} }; parent:[* =\u0026gt; Y,\u0026quot;bob\u0026quot;] // this one returns true if we find a parent of \u0026quot;bob\u0026quot; // same time it assigns parent to a string vector `Y` Field access Field access expressoin accesses fields inside constructs. Here is a recorcalled user:\nvar user1: user = { email = \u0026quot;[email protected]\u0026quot;, username = \u0026quot;someusername123\u0026quot;, 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:\n methods data Methods Methods are accesed the same way like routine member access.\nuser1.getName() Data There are multiple ways to acces data within the construct. The easiest one is by dot operator .:\nuser1.email // accessing the field through dot-accesed-memeber Another way is by using square bracket enclosed by name:\nuser1[email] // accessing the field through square-bracket-enclosed by name And lastly, by square bracket enclosed by index:\nuser1[0] // accessing the field through square-bracket-enclosed by index ","description":"","id":64,"section":"docs","tags":null,"title":"Access","uri":"https://follang.github.io/docs/200_expressions/300_exp/access/"},{"content":"FOL\u0026rsquo;s all possible code blocks:\nDECLARATION Variable var one = \u0026lt;expression\u0026gt;; ~var one = \u0026lt;expression\u0026gt;; ~var one: int = \u0026lt;expression\u0026gt;; ~var[] one: int[] = \u0026lt;expression\u0026gt;; ~var[opt,opt] one: int[opt,opt] = \u0026lt;expression\u0026gt;; ~var[] ( one: int[] = \u0026lt;expression\u0026gt;; two: int[] = \u0026lt;expression\u0026gt;; ) ~var[] one, two, three: int[] = \u0026lt;expression\u0026gt;; ~var[] one, two, three: int[], flt[], bol[] = \u0026lt;expression\u0026gt;; Functions fun one(two: int): int = { \u0026lt;expression\u0026gt; } ~fun one(two: int): int = { \u0026lt;expression\u0026gt; } ~log[] one(two: int): int = { \u0026lt;expression\u0026gt; } ~fun[] '!='(one, two: int): bol = { \u0026lt;expression\u0026gt; } ~pro[] (obj)one(two: int): int = { \u0026lt;expression\u0026gt; } ~pro[] (obj)'$': str = { \u0026lt;expression\u0026gt; } ~pro[] one[T: gen](two: int): int = { \u0026lt;expression\u0026gt; } Types typ user: rec = { \u0026lt;expression\u0026gt; }; ~typ[] ( one: rec[] = \u0026lt;expression\u0026gt;; two: rec[] = \u0026lt;expression\u0026gt;; ) ~typ[] user: rec = { \u0026lt;expression\u0026gt; }; ~typ[] user: rec[] = { \u0026lt;expression\u0026gt; }; ~typ[] user(blue): rec[] = { \u0026lt;expression\u0026gt; }; ~typ[] user(T: gen, N: int)(blue): obj ; ~ali[] five: arr[int, 5]; ~ali[] int: int; Packages use[] one: two = \u0026lt;expression\u0026gt;; ~use[] one: two = \u0026lt;expression\u0026gt;; ~use[] ( one: two = \u0026lt;expression\u0026gt;; two: two = \u0026lt;expression\u0026gt;; ) Macros def '$'(a: any): mac = '.to_string($)' def '~var': alt = 'var[~]' def 'str': def[] = 'str[new,mut,nor]' CONTROL Choice when(condition){ case (condition){} case (condition){} * {} }; when(variable){ is (value){}; is (value){}; * {}; }; when(variable){ in (iterator){}; in (iterator){}; * {}; }; when(iterable){ has (member){}; has (member){}; * {}; }; when(generic){ of (type){}; of (type){}; * {}; }; when(type){ on (channel){}; on (channel){}; }; Loops loop(condition){}; loop(iterable){}; LITERALS Function [a, b: int]{ \u0026lt;expression\u0026gt; } Constructs [name]{ \u0026lt;expression\u0026gt; } ","description":"","id":65,"section":"docs","tags":null,"title":"Blocks","uri":"https://follang.github.io/docs/200_expressions/blocks/"},{"content":"Rolling or list comprehension is a syntactic construct available FOL for creating a list based on existing lists. It follows the form of the mathematical set-builder notation - set comprehension.\nRolling has the same syntactic components to represent generation of a list in order from an input list or iterator:\n A variable representing members of an input list. An input list (or iterator). An optional predicate expression. And an output expression producing members of the output list from members of the input iterable that satisfy the predicate. The order of generation of members of the output list is based on the order of items in the input. Syntactically, rolling consist of an iterable containing an expression followed by a for statement. In FOL the syntax follows exacly the Python\u0026rsquo;s list comprehension syntax:\nvar aList: vec[] = { x for x in iterable if condition } Rolling provides an alternative syntax to creating lists and other sequential data types. While other methods of iteration, such as for loops, can also be used to create lists, rolling may be preferred because they can limit the number of lines used in your program.\nvar aList: vec[] = {..12}; var another: vec[] = { ( x * x ) for ( x in aList ) if ( x % 3 == 0 ) } var matrix: mat[int, int] = { x * y for ( x in {..5}, y in {..5} ) } ","description":"","id":66,"section":"docs","tags":null,"title":"Rolling","uri":"https://follang.github.io/docs/700_sugar/rolling/"},{"content":"Characters A character is a single Unicode element enclosed within quotes U+0022 (\u0026quot;) with the exception of U+0022 itself, which must be escaped by a preceding U+005C character (\\).\nvar aCharacter: chr = \u0026quot;z\\n\u0026quot; var anotherOne: str = \u0026quot;語\\n\u0026quot; Raw characters Raw character literals do not process any escapes. They are enclosed within single-quotes U+0027 (') with the exception of U+0027 itself:\nvar aCharacter: chr = 'z' Strings A string is a single or a sequence of Unicode elements enclosed within quotes U+0022 (\u0026quot;) with the exception of U+0022 itself, which must be escaped by a preceding U+005C character (\\).\nvar hiInEnglish: str = \u0026quot;Hello, world!\\n\u0026quot; var hInCantonese: str = \u0026quot;日本語\u0026quot; Line-breaks are allowed in strings. A line-break is either a newline (U+000A) or a pair of carriage return and newline (U+000D, U+000A). Both byte sequences are normally translated to U+000A, but as a special exception, when an unescaped U+005C character (\\ occurs immediately before the line-break, the U+005C character, the line-break, and all whitespace at the beginning of the next line are ignored. Thus a and b are equal:\nvar a: str = \u0026quot;foobar\u0026quot;; var b: str = \u0026quot;foo\\ bar\u0026quot;; assert(a,b); Escape sequences Some additional escapes are available in either character or non-raw string literals.\n code description \\p platform specific newline: CRLF on Windows, LF on Unix \\r, \\c carriage return \\n, \\l line feed (often called newline) \\f form feed \\t tabulator \\v vertical tabulator \\\\ backslash \\\u0026quot; quotation mark \\' apostrophe \\ \u0026lsquo;0\u0026rsquo;..\u0026lsquo;9\u0026rsquo;+ character with decimal value d; all decimal digits directly following are used for the character \\a alert \\b backspace \\e escape [ESC] \\x HH character with hex value HH; exactly two hex digits are allowed \\u HHHH unicode codepoint with hex value HHHH; exactly four hex digits are allowed \\u {H+} unicode codepoint; all hex digits enclosed in {} are used for the codepoint Raw strings Just like raw characters, raw string literals do not process any escapes either. They are enclosed within single-quotes U+0027 (') with the exception of U+0027 itself:\nvar hiInEnglish: str = 'Hello, world!' Booleans The two values of the boolean type are written true and false:\nvar isPresent: bol = false; ","description":"","id":67,"section":"docs","tags":null,"title":"Letters","uri":"https://follang.github.io/docs/100_lexical/strings/"},{"content":"Unpacking—also known as iterable destructuring—is another form of pattern matching used to extract data from collections of data. Take a look at the following example:\nvar start, *_ = { 1, 4, 3, 8 } .echo(start) // Prints 1 .echo(_) // Prints [4, 3, 8] In this example, we’re able to extract the first element of the list and ignore the rest. Likewise, we can just as easily extract the last element of the list:\nvar *_, end = { \u0026quot;red\u0026quot;, \u0026quot;blue\u0026quot;, \u0026quot;green\u0026quot; } .echo(end) // Prints \u0026quot;green\u0026quot; In fact, with pattern matching, we can extract whatever we want from a data set assuming we know it’s structure:\nvar start, *_, (last_word_first_letter, *_) = { \u0026quot;Hi\u0026quot;, \u0026quot;How\u0026quot;, \u0026quot;are\u0026quot;, \u0026quot;you?\u0026quot; } .echo(last_word_first_letter) // Prints \u0026quot;y\u0026quot; .echo(start) // Prints \u0026quot;Hi\u0026quot; Now, that has to be one of the coolest programming language features. Instead of extracting data by hand using indices, we can just write a pattern to match which values we want to unpack or destructure.\n","description":"","id":68,"section":"docs","tags":null,"title":"Unpacking","uri":"https://follang.github.io/docs/700_sugar/unpacking/"},{"content":"Inquiries are inline unit tests and are a part of the basic syntax sugar. In other words, we don’t have to import any libraries or build up any suites to run tests.\nInstead, FOL includes a couple of clauses for testing within the source code:\nfun sum(l: int...): int = { when (l.length()){ is 1 -\u0026gt; l[0]; * -\u0026gt; l[0] + sum(l[1:]); } where (self){ sum(8) is 8; sum(1, 2, 3) is 6; } } Here, we can see an awesome list sum function. Within the function, there are two basic cases: empty and not empty. In the empty case, the function returns 0. Otherwise, the function performs the sum.\nAt that point, most languages would be done, and testing would be an afterthought. Well, that’s not true in FOL. To add tests, we just include a where clause. In this case, we test an empty list and a list with an expected sum of 6.\nWhen the code is executed, the tests run. However, the tests are non-blocking, so code will continue to run barring any catastrophic issues.\n","description":"","id":69,"section":"docs","tags":null,"title":"Inquiry","uri":"https://follang.github.io/docs/700_sugar/inquiry/"},{"content":"A number is either an integer, floating-point or imaginary. The grammar for recognizing the kind of number is mixed.\nIntigers An integer has one of four forms:\n A decimal literal starts with a decimal digit and continues with any mixture of decimal digits and underscores. A hex literal starts with the character sequence U+0030 U+0078 (0x) and continues as any mixture (with at least one digit) of hex digits and underscores. An octal literal starts with the character sequence U+0030 U+006F (0o) and continues as any mixture (with at least one digit) of octal digits and underscores. A binary literal starts with the character sequence U+0030 U+0062 (0b) and continues as any mixture (with at least one digit) of binary digits and underscores. var decimal: int = 45; var hexadec: int = 0x6HF53BD5; var octal: int = 0o822371; var binary: int = 0b010010010; Underscore Underscore character U+005F (_) is a special character, that does not represent anything withing the number laterals. An integer lateral containing this character is the same as the one without. It is used only as a syntastc sugar:\nvar aNumber: int = 540_467; var bNumber: int = 540467; assert(aNumber, bNumber) Floating points A floating-point has one of two forms:\n A decimal literal followed by a period character U+002E (.). This is optionally followed by another decimal literal. A decimal literal that follows a period character U+002E (.). var aFloat: flt = 3.4; var bFloat: flt = .4; Imaginary numbers ","description":"","id":70,"section":"docs","tags":null,"title":"Numbers","uri":"https://follang.github.io/docs/100_lexical/numbers/"},{"content":"Chaining, also known as named parameter idiom, is a common syntax for invoking multiple method calls of a structure. Each method returns a structure, allowing the calls to be chained together in a single statement without requiring variables to store the intermediate results.\nIn order for this to work, the structure\u0026rsquo;s method needs to return the structure itself. For example (below), if we call the method add og container does\u0026rsquo;nt return anything, thus we cant chain further more.\ntyp continer[T: gen, G: int](): rec = { var collection: arr[G, T]; var point: int = 0; fun add(val: T) = { if (point \u0026lt; G) { collection.push(val) } else { error = \u0026quot;some error\u0026quot; } } fun add_2(val: T): Self = { if (point \u0026lt; G) { collection.push(val) } else { error = \u0026quot;some error\u0026quot; } } } var collection_1: continer[int, 5]; container_1.add(1).add(2) //this throws an error, because first `add` returns none container_1.add_2(1).add_2(2) //this works, because `add` return the object itself FOL, takes this into next level, in order to always work the chining (where it makes sense, of course) we uase double .. to indicate it..\ntyp continer[T: gen, G: int](): rec = { var collection: arr[G, T]; var point: int = 0; fun add(val: T) = { if (point \u0026lt; G) { collection.push(val) } else { error = \u0026quot;some error\u0026quot; } } } var collection_1: continer[int, 5]; container_1..add(1)..add(2) //here now it works, eventhoug `add` does not retunr `Self` //because symbol `..` always reuturns the object itself from the //the method call, not the value Method chaining eliminates an extra variable for each intermediate step. The developer is saved from the cognitive burden of naming the variable and keeping the variable in mind.\nMethod chaining has been referred to as producing a \u0026ldquo;train wreck\u0026rdquo; due to the increase in the number of methods that come one after another in the same line that occurs as more methods are chained together.\n","description":"","id":71,"section":"docs","tags":null,"title":"Chaining","uri":"https://follang.github.io/docs/700_sugar/chaining/"},{"content":"Operators Fol allows user defined operators. An operator is any combination of the following characters:\n= + - * / \u0026gt; . @ $ ~ \u0026amp; % \u0026lt; : ! ? ^ # ` \\ _ The grammar uses the terminal OP to refer to operator symbols as defined here.\nBrackets Bracket punctuation is used in various parts of the grammar. An open bracket must always be paired with a close bracket. Here are type of brackets used in FOL:\n bracket type purpose { } Curly brackets Code blocks, Namespaces, Containers [ ] Square brackets Type options, Container acces, Multithreading ( ) Round brackets Calculations, Comparisons, Argument passing \u0026lt; \u0026gt; Angle brackets The grammar uses the terminal BR to refer to operator symbols as defined here.\n","description":"","id":72,"section":"docs","tags":null,"title":"Symbols","uri":"https://follang.github.io/docs/100_lexical/symbols/"},{"content":"Lorem est tota propiore conpellat pectoribus de\npectora summo. Redit teque digerit hominumque toris verebor lumina non cervice\nsubde tollit usus habet Arctonque, furores quas nec ferunt. Quoque montibus nunc\ncaluere tempus\nThis article offers a sample of basic Markdown syntax that can be used in Hugo content files, also it shows whether basic HTML elements are decorated with CSS in a Hugo theme.\n Headings The following HTML \u0026lt;h1\u0026gt;—\u0026lt;h6\u0026gt; elements represent six levels of section headings. \u0026lt;h1\u0026gt; is the highest section level while \u0026lt;h6\u0026gt; is the lowest.\nH1 H2 H3 H4 H5 H6 Paragraph Xerum, quo qui aut unt expliquam qui dolut labo. Aque venitatiusda cum, voluptionse latur sitiae dolessi aut parist aut dollo enim qui voluptate ma dolestendit peritin re plis aut quas inctum laceat est volestemque commosa as cus endigna tectur, offic to cor sequas etum rerum idem sintibus eiur? Quianimin porecus evelectur, cum que nis nust voloribus ratem aut omnimi, sitatur? Quiatem. Nam, omnis sum am facea corem alique molestrunt et eos evelece arcillit ut aut eos eos nus, sin conecerem erum fuga. Ri oditatquam, ad quibus unda veliamenimin cusam et facea ipsamus es exerum sitate dolores editium rerore eost, temped molorro ratiae volorro te reribus dolorer sperchicium faceata tiustia prat.\nItatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sapicia is sinveli squiatum, core et que aut hariosam ex eat.\nBlockquotes The blockquote element represents content that is quoted from another source, optionally with a citation which must be within a footer or cite element, and optionally with in-line changes such as annotations and abbreviations.\nBlockquote without attribution Tiam, ad mint andaepu dandae nostion secatur sequo quae.\nNote that you can use Markdown syntax within a blockquote.\n Blockquote with attribution Don\u0026rsquo;t communicate by sharing memory, share memory by communicating.\n— Rob Pike1\n Tables Tables aren\u0026rsquo;t part of the core Markdown spec, but Hugo supports supports them out-of-the-box.\n Name Age Bob 27 Alice 23 Inline Markdown within tables Inline Markdown In Table italics bold strikethrough code Code Blocks Code block with backticks html \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html lang=\u0026quot;en\u0026quot;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026quot;UTF-8\u0026quot;\u0026gt; \u0026lt;title\u0026gt;Example HTML5 Document\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;p\u0026gt;Test\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; Code block indented with four spaces \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html lang=\u0026quot;en\u0026quot;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026quot;UTF-8\u0026quot;\u0026gt; \u0026lt;title\u0026gt;Example HTML5 Document\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;p\u0026gt;Test\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; Code block with Hugo\u0026rsquo;s internal highlight shortcode \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html lang=\u0026#34;en\u0026#34;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026#34;UTF-8\u0026#34;\u0026gt; \u0026lt;title\u0026gt;Example HTML5 Document\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;p\u0026gt;Test\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; List Types Ordered List First item Second item Third item Unordered List List item Another item And another item Nested list Item First Sub-item Second Sub-item Other Elements — abbr, sub, sup, kbd, mark GIF is a bitmap image format.\nH2O\nXn + Yn = Zn\nPress CTRL+ALT+Delete to end the session.\nMost salamanders are nocturnal, and hunt for insects, worms, and other small creatures.\n The above quote is excerpted from Rob Pike\u0026rsquo;s talk during Gopherfest, November 18, 2015. \u0026#x21a9;\u0026#xfe0e;\n ","description":"","id":73,"section":"blog","tags":["markdown","css","html","themes"],"title":"Markdown Syntax Guide","uri":"https://follang.github.io/blog/markdown-syntax/"}]