diff options
author | Joel Kronqvist <joel.kronqvist@iki.fi> | 2025-08-14 21:59:15 +0300 |
---|---|---|
committer | Joel Kronqvist <joel.kronqvist@iki.fi> | 2025-08-14 21:59:15 +0300 |
commit | 6f0c1b4a28b42f9c498e968964fffb511c9c9f36 (patch) | |
tree | 2802da0e44440fbf509b68ae12748173b0ad6877 | |
parent | f057211407df29c772ac18303f13d5564684979d (diff) | |
download | myslip-6f0c1b4a28b42f9c498e968964fffb511c9c9f36.tar.gz myslip-6f0c1b4a28b42f9c498e968964fffb511c9c9f36.zip |
doc: updated tutorial
-rw-r--r-- | TUTORIAL.md | 160 |
1 files changed, 119 insertions, 41 deletions
diff --git a/TUTORIAL.md b/TUTORIAL.md index 1ba6642..8e5165d 100644 --- a/TUTORIAL.md +++ b/TUTORIAL.md @@ -9,22 +9,23 @@ mentioning. Tour ----- +==== -**Arithmetic operations** +Arithmetic operations +--------------------- 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, @@ -32,66 +33,69 @@ multiple arguments can be used (even just one, even though that doesn't really make sense): ```console > (+ 1 2 3) -6 : int +6 : Int > (* 2 3 4 5) -120 : int +120 : Int ``` Decimals are truncated in division: ```console > (/ 5 2) -2 : int +2 : Int ``` -**Booleans** +Booleans +-------- 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 ``` -**Integer comparisons** +Integer comparisons +------------------- 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** +Variables +--------- Values can be bound to variables using the let expression. ```console > (let x 1) x saved > x -1 : int +1 : Int ``` The REPL interprets this as `((let x 1) x)`, which you could also type but would make a more cumbersome REPLing @@ -100,14 +104,15 @@ experience. Shadowing works as expected: ```console > ((let x 1) (+ x ((let x 2) x) x)) -4 : int +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 +--------- Functions are written in the form of `(fn [argument list] [argument type list] [return type] [function body])`. @@ -118,20 +123,21 @@ 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))) +> (let ++ (fn a Int Int (+ a 1))) ++ saved > (++ 1) -2 : int -> (let between (fn (a b c) (int int int) bool (and (< b c) (> b a)))) +2 : Int +> (let between (fn (a b c) (Int Int Int) bool (and (< b c) (> b a)))) between saved > (between 1 2 3) -true : bool +true : Bool > (between 1 0 3) -false : bool +false : Bool ``` -**Lists** +Lists +----- Lists in myslip correspond to what is known as tuples in many other programming languages. This difference exists because @@ -150,47 +156,119 @@ That's why constructing a list requires the operator > quote quote : (T -> (Quote T)) > (quote 1 2 3 4 5) -(quote 1 2 3 4 5) : (Quote (int int int int int)) +(quote 1 2 3 4 5) : (Quote (Int Int Int Int Int)) ``` In contrast from many other lisp-variants, in myslip sub-expressions are simplified. ```console > (quote (+ 1 1) (+ 2 2)) -(quote 2 4) : (Quote (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)) : (Quote ((int int) -> int) int (Quote (int int))) +(quote - 0 (quote 1 2)) : (Quote ((Int Int) -> Int) Int (Quote (Int Int))) ``` TODO: List destructuring -**Vectors** +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 : ((T ...) -> (Vector (T ...))) > (vector 1 2 3 4) -(vector 1 2 3 4) : (Vector (int ... int)) +(vector 1 2 3 4) : (Vector (Int ...)) ``` TODO: vector destructuring -**Understanding error messages** +Pattern matching +---------------- + +Values can be inspected using pattern matching. +For basic lists, the `case`-operator can be used. +It's syntax is: +```myslip +(case [condition] + ([pattern 1] [value 1]) + ([pattern 2] [value 2]) + ...) +``` + +Just note that every case expression needs to +have one wildcard pattern, to ensure exhaustiveness. + +Here's a very basic example: +```console +> (let x 1) +x saved +> (case (> x 5) (true (- x 1)) (_ x)) +1 : Int +> (case (quote 1 2 3 4 5) ((5 4 3 2 1) 0) ((a b c 4 e) 1) (_ 2)) +1 : Int +``` + +The list can be destructured into parts. If there +is a `..[variable name]` at the end of a pattern, +it matches the rest of the list. +```console +> (case (quote 1 2 3 4 5) ((h1 h2 ..tail) (+ h1 h2)) ((h ..t) h) (_ 0)) +3 : Int +``` + +Nesting in pattern matching works fine too. +```console +> (case (quote 1 2 (quote 3 4) 5) ((1 2 (quote 3 4) 5) true) (_ false)) +true : Bool +``` + +Pattern matching can be done on vectors too. +Just remember that the rest pattern `..r` needs to be at +the end of the pattern — not at the end of a subpattern. +```console +> (let myvec (vector 1 2 3 4 5)) +myvec saved +> (case myvec ((head ..tail) head) (_ 0)) +1 : Int +``` +Here's a failing example of trying to put a rest pattern at +the end of a subpattern: +```console +> (case (quote myvec false) (((head ..tail) false) head) (_ 0)) +Type error: unbound generic type 'T' in 'T' +``` +Try extracting the vector first through one pattern and +then pattern matching on the extracted vector for your +desired behaviour. + + +General recursion +----------------- + +General recursion in myslip is achieved through the +fixed point operator `fix`. + +TODO + + +Understanding error messages +---------------------------- + TODO: div zero TODO: unclosed parenthesis TODO: type errors Exercises ---------- +========= TODO |