mirror of
https://github.com/kanaka/mal.git
synced 2024-10-26 14:22:25 +03:00
Draft exercise suggesting native implementations of some built-in functions.
This commit is contained in:
parent
a003046c8d
commit
0544b52f1a
49
docs/exercise.md
Normal file
49
docs/exercise.md
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
Once you have a working implementation, you may want to implement
|
||||||
|
parts of the process inside the MAL language itself. This has no other
|
||||||
|
purpose than learning the MAL language. Once it exists, a built-in
|
||||||
|
implementation will always be more efficient than a native
|
||||||
|
implementation. Also, the functions described in MAL process are
|
||||||
|
selected for educative purposes, so portability accross
|
||||||
|
implementations does not matter much.
|
||||||
|
|
||||||
|
You may easily check your answers by passing them directly to the
|
||||||
|
interpreter. They will hide the built-in functions carrying the same
|
||||||
|
names, and the usual tests (with REGRESS=1) will check them. The
|
||||||
|
`runtest.py` script provide a convenient command-line parameter to
|
||||||
|
pass a command like 'load-file' before running the testsuite.
|
||||||
|
|
||||||
|
Some solutions are given in the `examples` directory. Feel free to
|
||||||
|
submit new solutions, or new exercises.
|
||||||
|
|
||||||
|
|
||||||
|
- Implement the following functions with other built-in functions.
|
||||||
|
- `nil?`, `true?` and `false?`
|
||||||
|
- `empty?`
|
||||||
|
- `sequential?`
|
||||||
|
|
||||||
|
- Implement `>`, `<=` and `>=` with `<`.
|
||||||
|
|
||||||
|
- Implement the following non-recursive functions.
|
||||||
|
- `hash-map`
|
||||||
|
- `list`
|
||||||
|
- `prn`
|
||||||
|
- `swap!`
|
||||||
|
|
||||||
|
- Implement `map` with a recursion.
|
||||||
|
|
||||||
|
- Implement the `do` special as a non-recursive function. The special
|
||||||
|
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 `apply` as a macro.
|
||||||
|
|
||||||
|
- Implement maps using lists.
|
||||||
|
FIXME: Is dissoc use anywhere? It makes this implememtation and the
|
||||||
|
process more complex.
|
||||||
|
|
||||||
|
- Implement quoting within MAL.
|
||||||
|
|
||||||
|
- Implement macros within MAL.
|
48
examples/exercises.mal
Normal file
48
examples/exercises.mal
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
;; These are the answers to the questions in ../docs/exercise.md.
|
||||||
|
|
||||||
|
(def! nil? (fn* [x] (= x nil )))
|
||||||
|
(def! true? (fn* [x] (= x true )))
|
||||||
|
(def! false? (fn* [x] (= x false)))
|
||||||
|
|
||||||
|
(def! empty? (fn* [xs] (= 0 (count xs))))
|
||||||
|
|
||||||
|
(def! sequential? (fn* [x] (if (list? x) true (if (vector? x) true false))))
|
||||||
|
|
||||||
|
(def! > (fn* [a b] (< b a) ))
|
||||||
|
(def! <= (fn* [a b] (if (< b a) false true)))
|
||||||
|
(def! >= (fn* [a b] (if (< a b) false true)))
|
||||||
|
|
||||||
|
(def! hash-map (fn* [& xs] (apply assoc {} xs)))
|
||||||
|
(def! list (fn* [& xs] xs))
|
||||||
|
(def! prn (fn* [& xs] (println (apply pr-str xs))))
|
||||||
|
(def! swap! (fn* [a f & xs] (reset! a (apply f (deref a) xs))))
|
||||||
|
|
||||||
|
(def! map
|
||||||
|
(fn* [f xs]
|
||||||
|
(if (empty? xs)
|
||||||
|
()
|
||||||
|
(cons (f (first xs)) (map f (rest xs))))))
|
||||||
|
|
||||||
|
(def! do2 (fn* [& xs] (nth xs (- (count xs) 1))))
|
||||||
|
|
||||||
|
(defmacro! let2
|
||||||
|
;; Must be a macro because the first argument must not be evaluated.
|
||||||
|
(fn* [binds form]
|
||||||
|
(if (empty? binds)
|
||||||
|
form
|
||||||
|
;; This let* increases the readability, but the values could
|
||||||
|
;; easily be replaced below.
|
||||||
|
(let* [key (nth binds 0)
|
||||||
|
val (nth binds 1)
|
||||||
|
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)))
|
Loading…
Reference in New Issue
Block a user