exercices: fix apply again. It must be a function, not a macro.
[jackhill/mal.git] / docs / exercise.md
CommitLineData
0544b52f
NB
1Once you have a working implementation, you may want to implement
2parts of the process inside the MAL language itself. This has no other
3purpose than learning the MAL language. Once it exists, a built-in
4implementation will always be more efficient than a native
5implementation. Also, the functions described in MAL process are
6selected for educative purposes, so portability accross
7implementations does not matter much.
8
9You may easily check your answers by passing them directly to the
10interpreter. They will hide the built-in functions carrying the same
11names, and the usual tests (with REGRESS=1) will check them. The
12`runtest.py` script provide a convenient command-line parameter to
13pass a command like 'load-file' before running the testsuite.
14
15Some solutions are given in the `examples` directory. Feel free to
16submit new solutions, or new exercises.
17
1ca3ee3d
NB
18- Implement `nil?`, `true?`, `false?` and `sequential?` with other
19 built-in functions.
0544b52f
NB
20
21- Implement `>`, `<=` and `>=` with `<`.
22
1ca3ee3d
NB
23- Implement `hash-map`, `list`, `prn` and `swap!` as non-recursive
24 functions.
25
26- Implement `count`, `nth`, `map`, `concat` and `conj` with the empty
27 constructor `()`, `empty?`, `cons`, `first` and `rest`.
28
29 Let `count` and `nth` benefit from tail call optimization.
0544b52f 30
1ca3ee3d 31 Try to replace explicit recursions with calls to `reduce` and `foldr`.
0544b52f
NB
32
33- Implement the `do` special as a non-recursive function. The special
34 form will hide your implementation, so in order to test it, you will
35 need to give it another name and adapt the test accordingly.
36
304930e7
NB
37- Implement `let*` as a macro that uses `fn*` and recursion.
38 The same remark applies.
0544b52f 39
1ca3ee3d 40- Implement `apply`.
0544b52f
NB
41
42- Implement maps using lists.
304930e7
NB
43 - Recall how maps must be evaluated.
44 - In the tests, you may want to replace `{...}` with `(hash-map ...)`.
45 - An easy solution relies on lists alterning keys and values, so
46 that the `hash-map` is only a list in reverse order so that the
47 last definition takes precedence during searches.
48 - As a more performant solution will use lists to construct trees,
49 and ideally keep them balanced. You will find examples in most
50 teaching material about functional languages.
51 - Recall that `dissoc` is an optional feature. One you can implement
52 dissoc is by assoc'ing a replacement value that is a magic delete
53 keyword (e.g.: `__..DELETED..__`) which allows you to shadow
54 values in the lower levels of the structure. The hash map
55 functions have to detect that and do the right thing. e.g. `(keys
56 ...)` might have to keep track of deleted values as it is scanning
57 the tree and not add those keys when it finds them further down
58 the tree.
0544b52f
NB
59
60- Implement quoting within MAL.
61
62- Implement macros within MAL.