summaryrefslogtreecommitdiff
path: root/macros/core.fnl
diff options
context:
space:
mode:
authorAndrey Orst <andreyorst@gmail.com>2020-10-31 14:27:46 +0300
committerAndrey Orst <andreyorst@gmail.com>2020-10-31 14:27:46 +0300
commit596089aece8383bd374621babff1a14f99413dba (patch)
tree44d26accf16f92fe69d42b2c4e72e944cbc9c9f7 /macros/core.fnl
parenteeb77bd0c1e251e0c84ff55f178bb4f2beb78f24 (diff)
feature(macros): implement simple multimethods
Diffstat (limited to 'macros/core.fnl')
-rw-r--r--macros/core.fnl29
1 files changed, 29 insertions, 0 deletions
diff --git a/macros/core.fnl b/macros/core.fnl
index be0c1bb..d107ad6 100644
--- a/macros/core.fnl
+++ b/macros/core.fnl
@@ -138,4 +138,33 @@
:else (error "expected table as first argument"))
to#))))
+(fn first [tbl]
+ (. tbl 1))
+
+(fn rest [tbl]
+ [(unpack tbl 2)])
+
+(fn string? [x]
+ (= (type x) :string))
+
+(fn* core.defmulti
+ [name & opts]
+ (let [docstring (if (string? (first opts)) (first opts))
+ opts (if docstring (rest opts) opts)
+ dispatch-fn (first opts)]
+ `(local ,name
+ (let [multimethods# {}]
+ (setmetatable {} {:__call
+ (fn [_# ...]
+ ,docstring
+ ((or (. multimethods# (,dispatch-fn ...))
+ (. multimethods# :default)) ...))
+ :multimethods multimethods#})))))
+
+(fn* core.defmethod
+ [multifn dispatch-val & fn-tail]
+ `(tset (. (getmetatable ,multifn) :multimethods)
+ ,dispatch-val
+ (fn ,(unpack fn-tail))))
+
core