|
|
@@ -1,3 +1,9 @@
|
|
|
+---
|
|
|
+title: Maat Programming Language Specification
|
|
|
+author: Kueppo Tcheukam J. W.
|
|
|
+email: tcheukueppo@yandex.com
|
|
|
+---
|
|
|
+
|
|
|
# Maat
|
|
|
|
|
|
`Maat` is a multi-paradigm general purpose programming language that empowers
|
|
|
@@ -34,7 +40,7 @@ for its for implementation.
|
|
|
- `-`: (b) negate the operand
|
|
|
- `+`: (b)
|
|
|
- `~`: (b) binary complement
|
|
|
-- `…` or `...`: (b) Array destruction operator in the context of list assingments and function calls
|
|
|
+- `…` or `...`: (b) Destructing operator in assignments and Accumulator operator in functions
|
|
|
- `^`: (p) `^5` return an array of element i.e from `0` to `5`
|
|
|
- `√`: (p) sqaure root operator
|
|
|
- `⁰ ¹ ² ³ ⁴ ⁵ ⁶ ⁷ ⁸ ⁹`: (b) super-script power operators
|
|
|
@@ -44,7 +50,8 @@ for its for implementation.
|
|
|
- `defined`: (b) check if a varible is `nil` and return true otherwise
|
|
|
- `sleep`: (b) call sleep() syscall
|
|
|
- `return`: (b) return from a function
|
|
|
-- `exit`: exit program with given exit code
|
|
|
+- `assert`: (b) test an assertion
|
|
|
+- `exit`: (b) exit program with given exit code
|
|
|
|
|
|
## Named list operators
|
|
|
|
|
|
@@ -193,12 +200,12 @@ made to temporal variables remains local to the scope from where it was declare
|
|
|
thus the referenced variables remains untouched. You cannot localize lexically scoped
|
|
|
variables.
|
|
|
|
|
|
-Declare package variables with the keyword `global`, lexically scoped variables
|
|
|
+Declare package variables with the keyword `pkg`, lexically scoped variables
|
|
|
with `var` and temporal variable with `temp`.
|
|
|
|
|
|
```js
|
|
|
package One::Two {
|
|
|
- glob x = a<one two three>
|
|
|
+ pkg x = qa<one two three>
|
|
|
|
|
|
var a = { one => 1 }
|
|
|
{
|
|
|
@@ -308,33 +315,34 @@ like simple variable we use in our Maat programs
|
|
|
|
|
|
Maat has ... builtin objects, types are objects and objects are types, check details on each types here.
|
|
|
|
|
|
-- Any
|
|
|
-- Bool
|
|
|
-- Num
|
|
|
-- Str
|
|
|
-- Range
|
|
|
-- Array
|
|
|
-- Map
|
|
|
-- Set
|
|
|
-- MSet
|
|
|
-- Bag
|
|
|
-- MBag
|
|
|
-- Lazy
|
|
|
-- Fun
|
|
|
-- Regex
|
|
|
-- Ma
|
|
|
-- Work
|
|
|
-- Chan
|
|
|
-- Socket
|
|
|
-- Socket::Work
|
|
|
-- Proc
|
|
|
-- Proc::Work
|
|
|
-- Pipe
|
|
|
-- File
|
|
|
-- Dir
|
|
|
-- Date
|
|
|
-- Sys
|
|
|
-- Term
|
|
|
+- [`Any`](./objects/Any.md)
|
|
|
+- [`Bool`](./objects/Bool.md)
|
|
|
+- [`Num`](./objects/Num.md)
|
|
|
+- [`Str`](./objects/Str.md)
|
|
|
+- [`Range`](./objects/Range.md)
|
|
|
+- [`Array`](./objects/Array.md)
|
|
|
+- [`Map`](./objects/Map.md)
|
|
|
+- [`Set`](./objects/Set.md)
|
|
|
+- [`MSet`](./objects/MSet.md)
|
|
|
+- [`Bag`](./objects/Bag.md)
|
|
|
+- [`MBag`](./objects/MBag.md)
|
|
|
+- [`Lazy`](./objects/Lazy.md)
|
|
|
+- [`Fun`](./objects/Fun.md)
|
|
|
+- [`GFun`](./objects/GFun.md)
|
|
|
+- [`Regex`](./objects/Regex.md)
|
|
|
+- [`Ma`](./objects/Ma.md)
|
|
|
+- [`Work`](./objects/Work.md)
|
|
|
+- [`Chan`](./objects/Chan.md)
|
|
|
+- [`Socket`](./objects/Socket.md)
|
|
|
+- [`Socket::Work`](./objects/Socket::Work.md)
|
|
|
+- [`Proc`](./objects/Proc.md)
|
|
|
+- [`Proc::Work`](./objects/Proc::Work.md)
|
|
|
+- [`Pipe`](./objects/Pipe.md)
|
|
|
+- [`File`](./objects/File.md)
|
|
|
+- [`Dir`](./objects/Dir.md)
|
|
|
+- [`Date`](./objects/Date.md)
|
|
|
+- [`Sys`](./objects/Sys.md)
|
|
|
+- [`Term`](./objects/Term.md)
|
|
|
|
|
|
**NB**: Take note of the following conventions about syntax definition
|
|
|
|
|
|
@@ -554,7 +562,7 @@ for a.lazy
|
|
|
|
|
|
7. Generator function with `take`
|
|
|
|
|
|
-A generator
|
|
|
+A generator function
|
|
|
|
|
|
The `take` keyword pauses generator function execution and the
|
|
|
|
|
|
@@ -767,30 +775,45 @@ sleep
|
|
|
|
|
|
## topic variable `_`
|
|
|
|
|
|
-The type I variable `_` is called a topic variable, this variable operates on anonymous
|
|
|
-functions and flow control blocks. Its usage in an anonymous function directly implies
|
|
|
-that the anonymous function in question is supposed to recieved a single argument when
|
|
|
-called but that argument was unamed and hence `_` defaults to it.
|
|
|
+The type I variable `_` is called a topic variable, this variable operates on
|
|
|
+anonymous functions and flow control blocks. The usage of a topic variable when
|
|
|
+calling an anonymous function implies the anonymous function takes a single
|
|
|
+argument whose parameter wasn't explicitly declared with `|...|` and hence
|
|
|
+defaults to `_`.
|
|
|
|
|
|
-You can omit the name of the topic variable when calling a method on the content it refers to.
|
|
|
+It is possible to omit `_` when calling a method on the content of the topic
|
|
|
+variable.
|
|
|
+
|
|
|
+```raku
|
|
|
+var anony = { say _.Str * 2 }
|
|
|
+
|
|
|
+# Output: tanzaniatanzania
|
|
|
+anony.call("tanzania")
|
|
|
+
|
|
|
+# Err: takes only one arg as the topic var is used in anony
|
|
|
+anony.call("a", "b")
|
|
|
|
|
|
-```
|
|
|
# .ucfirst is the same as _.ucfirst
|
|
|
var ar = qm{tcheukam madjou monthe}
|
|
|
say ar.map({.ucfirst})
|
|
|
+```
|
|
|
+
|
|
|
+The topic variable in an anonymous function with declared or expecting no
|
|
|
+parameters refers to if exists from outer scopes.
|
|
|
|
|
|
+The method `.times` of the `Num` type expects no argument when called and thus
|
|
|
+refers to the topic variable from the lowest level outer scope.
|
|
|
+
|
|
|
+```raku
|
|
|
# Output: 88888888 666666 666666
|
|
|
ar.map(:.len).each { .times { .print } }
|
|
|
```
|
|
|
|
|
|
-```
|
|
|
-```
|
|
|
-
|
|
|
-Maat has support for multiple dispatching and named arguments. Mixing named arguments
|
|
|
-with unnamed ones brings a lot of confusion in your code and hence either you name all
|
|
|
-your arguments or you don't name anything at all.
|
|
|
+Maat has support for multiple dispatching and named arguments. Mixing named
|
|
|
+arguments with unnamed ones brings a lot of confusion in your code and hence
|
|
|
+either you name all your arguments or you don't name anything at all.
|
|
|
|
|
|
-```
|
|
|
+```ruby
|
|
|
fun call(c, n) { c.call(_) for ^n }
|
|
|
call({ .say }, 5)
|
|
|
|
|
|
@@ -814,18 +837,39 @@ fun mul(s) { s * 2 }
|
|
|
|
|
|
mul("one").say # Output: oneone
|
|
|
mul("two", 5).say # Output: twotwotwotwo
|
|
|
+```
|
|
|
+
|
|
|
+Maat has what we call an accumulator and destructor operator, let us cover
|
|
|
+everything here. The accumulator operator is a postfix operator used to collect
|
|
|
+the rest of extra indefinite number of arguments as an array into the last
|
|
|
+declared parameter of that called function/method. This is done by appending
|
|
|
+`…` to the last declared parameter at function definition.
|
|
|
|
|
|
+```
|
|
|
# using the array accumulator operator for variadic arguments
|
|
|
-fun count(name, counts…) {
|
|
|
- printfln "You have %d %ss", counts.sum, name
|
|
|
+fun count(name, …counts) {
|
|
|
+ printf "You have %d %ss\n", count.len > 0 ? counts.sum : 0, name
|
|
|
}
|
|
|
|
|
|
-count("pineaple", 2, 4, 10)
|
|
|
+count("pineaple", 2, 4, 10) # Output: "You have 16 pineaples"
|
|
|
+count("orange") # Output: "You have 0 oranges"
|
|
|
+
|
|
|
+fun sum(...ar) { ar.sum }
|
|
|
+
|
|
|
+# does not make sense, fails at compilation
|
|
|
+fun bad_func(a, ...b, c) { ... }
|
|
|
+fun bad_func(...a, b, ...c) { ... }
|
|
|
+fun bad_func(a, ...b, ...c) { ... }
|
|
|
```
|
|
|
|
|
|
-Function as well as methods do have support for the `save` trait, the `save` trait
|
|
|
-caches the return value of the function for letter retrieval if another call was
|
|
|
-made
|
|
|
+The destructor operator on the other hand is
|
|
|
+
|
|
|
+## Traits
|
|
|
+
|
|
|
+Functions as well as methods support the `:save` trait, the `:save` trait
|
|
|
+caches the return value of a function call to avoid recomputation of the
|
|
|
+same function call in recursive calls. This trait can help you do dynamic
|
|
|
+programming with less overhead.
|
|
|
|
|
|
```
|
|
|
fun fib(n) :save {
|
|
|
@@ -837,18 +881,25 @@ fun fib(n) :save {
|
|
|
|
|
|
```
|
|
|
role D { ... }
|
|
|
-role E { ... }
|
|
|
+
|
|
|
+role E {
|
|
|
+}
|
|
|
|
|
|
class B { ... }
|
|
|
class C { ... }
|
|
|
|
|
|
# "is" for inheritance and "does" for roles
|
|
|
class A :is(B, C) :does(D, E) {
|
|
|
- has x :ro # read-only attribute, ro: say A.x; not possible: A.x = "some value"
|
|
|
- has y :rw = 0 # read-write attribute with default value '0', write: A.y = 2; read: say A.y
|
|
|
- has z #
|
|
|
+ # read-only attribute, ro: say A.x; not possible: A.x = "some value"
|
|
|
+ has x :ro
|
|
|
|
|
|
- state count = 0 # static variable which is accessible to all objects via class 'A': A.count
|
|
|
+ # read-write attribute with default value '0', write: A.y = 2; read: say A.y
|
|
|
+ has y :rw = 0
|
|
|
+
|
|
|
+ has z
|
|
|
+
|
|
|
+ # static variable which is accessible to all objects via class 'A': A.count
|
|
|
+ state count = 0
|
|
|
|
|
|
# static method (A.m()), self isn't valid here
|
|
|
state meth m() {
|
|
|
@@ -860,23 +911,22 @@ class A :is(B, C) :does(D, E) {
|
|
|
...
|
|
|
}
|
|
|
|
|
|
- mul meth amethod() {}
|
|
|
+ mul meth amethod() { ... }
|
|
|
|
|
|
# takes a parameter x
|
|
|
- mul meth amethod(x) {}
|
|
|
+ mul meth amethod(x) { ... }
|
|
|
|
|
|
# defining a method 'priv' as private, oi means only-in
|
|
|
- meth priv() :oi {}
|
|
|
+ meth priv() :oi { ... }
|
|
|
}
|
|
|
```
|
|
|
|
|
|
List of traits supported by class attributes
|
|
|
|
|
|
-- `rw`: Attribute is read-write
|
|
|
-- `ro`: Attribute is read-only
|
|
|
-- `built`: Make attribute private but can only also be written from outside the object only via object instanciation
|
|
|
-
|
|
|
-We also have the `oi` trait which makes a method private
|
|
|
+- `rw`: Make attribute read-write
|
|
|
+- `ro`: Make attribute read-only
|
|
|
+- `built`: Make attribute private but can be set when instanciating
|
|
|
+- `oi`: Make method private to the class
|
|
|
|
|
|
To every object is associated a metaobject which permits object introspection, given an object
|
|
|
`obj`, you can introspect this method via its metaobject by using the `.^` method call operator.
|