/
invoke.clj
39 lines (35 loc) · 1003 Bytes
/
invoke.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
(ns contextual.impl.invoke
(:require
[contextual.impl.protocols :as p]))
(defrecord Fn* [f args]
p/IContext
(-invoke [this ctx]
(apply f (map #(p/-invoke % ctx) args))))
(defmacro ^:private def-fns []
(let [f 'f
invoke '-invoke
name "Fn"
ctx 'ctx
defs
(for [n (range 20)
:let [args (map (comp symbol #(str "a" %)) (range n))
rec (symbol (str name n))
constructor (symbol (str "->" rec))
body (list* f (map (fn [arg] `(p/-invoke ~arg ~ctx)) args))]]
{:rec
`(defrecord ~rec [~f ~@args]
p/IContext
(~invoke [~'this ~ctx]
~body))
:call
(if (= n 20)
`([~f ~@args] (->Fn* ~f [~@args]))
`([~f ~@args] (~constructor ~f ~@args)))})]
`(do
~@(map :rec defs)
(defn ~'->fn ~@(map :call defs)))))
(def-fns)
(comment
(p/-invoke
(->fn inc 1)
nil))