1
1
mirror of https://github.com/kanaka/mal.git synced 2024-08-16 17:20:23 +03:00

exercises: fix apply reimplementation, add Joel's hints for maps

This commit is contained in:
Nicolas Boulenguez 2019-05-09 20:56:11 +02:00
parent 0544b52f1a
commit 304930e749
2 changed files with 30 additions and 13 deletions

View File

@ -35,14 +35,28 @@ submit new solutions, or new exercises.
form will hide your implementation, so in order to test it, you will
need to give it another name and adapt the test accordingly.
- Implement `let*` as a macro that uses `fn*` and recursionn. The same
remark applies.
- Implement `let*` as a macro that uses `fn*` and recursion.
The same remark applies.
- Implement `apply` as a macro.
- Implement maps using lists.
FIXME: Is dissoc use anywhere? It makes this implememtation and the
process more complex.
- Recall how maps must be evaluated.
- In the tests, you may want to replace `{...}` with `(hash-map ...)`.
- An easy solution relies on lists alterning keys and values, so
that the `hash-map` is only a list in reverse order so that the
last definition takes precedence during searches.
- As a more performant solution will use lists to construct trees,
and ideally keep them balanced. You will find examples in most
teaching material about functional languages.
- Recall that `dissoc` is an optional feature. One you can implement
dissoc is by assoc'ing a replacement value that is a magic delete
keyword (e.g.: `__..DELETED..__`) which allows you to shadow
values in the lower levels of the structure. The hash map
functions have to detect that and do the right thing. e.g. `(keys
...)` might have to keep track of deleted values as it is scanning
the tree and not add those keys when it finds them further down
the tree.
- Implement quoting within MAL.

View File

@ -37,12 +37,15 @@
more (rest (rest binds))]
`((fn* [~key] (let2 ~more ~form)) ~val)))))
(defmacro! apply
(fn* [& xs]
(;; Rewrite (f a b [c d]) to (f a b c d).
(def! rec
(fn* [lst]
(if (= 1 (count lst))
(first lst) ; last argument must be a sequence
(cons (first lst) (rec (rest lst))))))
xs)))
(def! apply
(let* [
;; (a b [c d]) -> (a b c d)
flat_end (fn* [xs]
(if (= 1 (count xs))
(first xs) ; [c d] above
(cons (first xs) (flat_end (rest xs)))))
;; x -> 'x to protect the already-evaluated arguments.
quote_elt (fn* [x] `(quote ~x))
]
(fn* [& xs]
(eval (map quote_elt (flat_end xs))))))