-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuilder.carp
More file actions
69 lines (67 loc) · 2.46 KB
/
builder.carp
File metadata and controls
69 lines (67 loc) · 2.46 KB
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
; implementing the builder pattern for a struct containing
; arrays and maps.
;
; this allows you to write things such as:
; (deftype T [
; x Int
; y (Map Int String)
; z (Array Float)
; ])
;
; ; these will generate add-to-y and add-to-z
; (map-builder T y)
; (array-builder T z)
;
; (defn main []
; (println* &(=> (T.init 0 {} [])
; (T.set-x 4)
; (T.add-to-y &3 "hi")
; (T.add-to-z 15.6f))))
;
; this macro basically just emits templated code:
; a module containing to functions called `add-to-<prop>`
; and `add-to-<prop>!`, respectively.
(defmacro map-builder [md prop]
; we enter the module that we’re passed
(list 'defmodule md
; we use Symbol.concat to concatenate the prefix and property
; name, and add an array of the object, key, and value of what
; we want to add
(list 'defn (Symbol.concat ['add-to- prop]) (array 'o 'k 'v)
; we use the updater function to put something in the map
; contained in the property of our type, trusting it all
; works out. otherwise the typechecker will complain
(list (Symbol.concat ['update- prop]) 'o
'(ref (fn [map] (Map.put map k v)))))
; the in-place version is much easier, though the head almost
; looks the same
(list 'defn (Symbol.concat ['add-to- prop '!]) (array 'o 'k 'v)
; the function body will just get the property and mutate it
; in place
(list 'Map.put! (list prop 'o) 'k 'v)))
; all of the above would mean that this:
; (map-builder T y)
; would desugar to this:
; (defmodule T
; (defn add-to-y [o k v]
; (update-y o &(fn [m] (Map.put m k v))))
; (defn add-to-y! [o k v]
; (Map.put! (y o) k v)))
; which is actually pretty readable!
)
; okay, the same deal, but for arrays
(defmacro array-builder [md prop]
(list 'defmodule md
; we only need one argument in addition to the object here,
; i called it `e`
(list 'defn (Symbol.concat ['add-to- prop]) (array 'o 'e)
; same deal as above, but we call `Array.push-back` instead
; of `Map.put`, as we did in the map version
(list (Symbol.concat ['update- prop]) 'o
'(ref (fn [a] (Array.push-back a e)))))
; the same applies here, instead of `Map.put! we write
; `Array.push-back!`
(list 'defn (Symbol.concat ['add-to- prop '!]) (array 'o 'e)
(list 'Array.push-back! (list prop 'o) 'e)))
; as an exercise, you can try expanding this version by hand!
)