aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-14 21:59:15 +0300
committerJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-14 21:59:15 +0300
commit6f0c1b4a28b42f9c498e968964fffb511c9c9f36 (patch)
tree2802da0e44440fbf509b68ae12748173b0ad6877
parentf057211407df29c772ac18303f13d5564684979d (diff)
downloadmyslip-6f0c1b4a28b42f9c498e968964fffb511c9c9f36.tar.gz
myslip-6f0c1b4a28b42f9c498e968964fffb511c9c9f36.zip
doc: updated tutorial
-rw-r--r--TUTORIAL.md160
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