diff options
-rw-r--r-- | TUTORIAL.md | 120 |
1 files changed, 96 insertions, 24 deletions
diff --git a/TUTORIAL.md b/TUTORIAL.md index 9494859..74384b1 100644 --- a/TUTORIAL.md +++ b/TUTORIAL.md @@ -18,19 +18,29 @@ Addition, multiplication, subtraction and division are supported with +, *, - and / respectively. ```console > (+ 1 1) -2 : Int +2 : int > (* 2 3) -6 : Int +6 : int > (- 5 4) -1 : Int +1 : int > (/ 4 2) -2 : Int +2 : int +``` + +As addition and multiplication are associative, +multiple arguments can be used (even just one, +even though that doesn't really make sense): +```console +> (+ 1 2 3) +6 : int +> (* 2 3 4 5) +120 : int ``` Decimals are truncated in division: ```console > (/ 5 2) -2 : Int +2 : int ``` @@ -40,17 +50,17 @@ Myslip supports booleans and `and`, `or`, `xor` and `not` for their comparisons. ```console > true -true : Bool +true : bool > false -false : Bool +false : bool > (and true true) -true : Bool +true : bool > (or true false) -true : Bool +true : bool > (xor true true) -false : Bool +false : bool > (not true) -false : Bool +false : bool ``` @@ -60,17 +70,64 @@ To generate booleans from integers, some basic and quite self-explanatory operators are supplied. ```console > (> 2 1) -true : Bool +true : bool > (< 1 2) -true : Bool +true : bool > (>= 1 1) -true : Bool +true : bool > (<= 1 1) -true : Bool +true : bool > (= 1 1) -true : Bool +true : bool > (!= 1 1) -false : Bool +false : bool +``` + + +**Variables** + +Values can be bound to variables using the let expression. +```console +> (let x 1) +Bind saved +> x +1 : int +``` +The REPL interprets this as `((let x 1) x)`, which you +could also type but would make a more cumbersome REPLing +experience. + +Shadowing works as expected: +```console +> ((let x 1) (+ x ((let x 2) x) x)) +4 : int +``` +Here, before the definition inside the addition, `x = 1`, +and after it it is too, while in the middle term where +`x = 2` is defined, `x = 2`. + + +**Functions** + +Functions are written in the form of +`(fn [argument list] [argument type list] [return type] [function body])`. +They don't have names of themselves, but they can be bound +using `let`. + +The following example features a simple increment function +and a function for checking if a integer is between two +others. +```console +> (let ++ (fn a int int (+ a 1))) +Bind saved +> (++ 1) +2 : int +> (let between (fn (a b c) (int int int) bool (and (< b c) (> b a)))) +Bind saved +> (between 1 2 3) +true : bool +> (between 1 0 3) +false : bool ``` @@ -91,27 +148,42 @@ That's why constructing a list requires the operator `quote`: ```console > quote -quote : (T -> T) +quote : (T -> (Quote T)) > (quote 1 2 3 4 5) -(quote 1 2 3 4 5) : (Int Int Int Int Int) +(quote 1 2 3 4 5) : (Quote (int int int int int)) ``` -As hinted above, `quote` is typewise the identity function. -Behaviorally it does though simplify sub-expressions. +In contrast from many other lisp-variants, in myslip +sub-expressions are simplified. ```console > (quote (+ 1 1) (+ 2 2)) -(quote 2 4) : (Int Int) +(quote 2 4) : (Quote (int int)) ``` The elements of a list can of course be of different types: ```console -> (quote + 0 (quote 1 2)) -(quote + 0 (quote 1 2)) : (((Int Int) -> Int) Int (Int Int)) +> (quote - 0 (quote 1 2)) +(quote - 0 (quote 1 2)) : (Quote ((int int) -> int) int (Quote (int int))) ``` TODO: List destructuring +**Vectors** + +Vectors behave roughly the same as lists, except +their length is not specified on type-level, and +their elements can be only of one type. +```console +> vector +vector : ((T ... T) -> (Vector (T ... T))) +> (vector 1 2 3 4) +(vector 1 2 3 4) : (Vector (int ... int)) +``` + +TODO: vector destructuring + + **Understanding error messages** TODO: div zero TODO: unclosed parenthesis |