-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathdefclass.clj
More file actions
79 lines (66 loc) · 2.03 KB
/
Copy pathdefclass.clj
File metadata and controls
79 lines (66 loc) · 2.03 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
70
71
72
73
74
75
76
77
;; inheritence
(declare this find-method)
(defn new-object [klass]
(let [state (ref {})]
(fn thiz [command & args]
(condp = command
:class klass
:class-name (klass :name)
:set! (let [[k v] args]
(dosync (alter state assoc k v))
nil)
:get (let [[key] args]
(key @state))
(let [method (klass :method command)]
(if-not method
(throw (RuntimeException. (str "Unable to respond to " command))))
(binding [this thiz]
(apply method args)))))))
(defn new-class [class-name parent methods]
(fn klass [command & args]
(condp = command
:name (name class-name)
:parent parent
:new (new-object klass)
:methods methods
:method (let [[method-name] args]
(find-method method-name klass)))))
(def OBJECT (new-class :OBJECT nil {}))
(defn find-method [method-name klass]
(or ((klass :methods) method-name)
(if-not (= #'OBJECT klass)
(find-method method-name (klass :parent)))))
(defn method-spec [sexpr]
(let [name (keyword (second sexpr))
body (next sexpr)]
[name (conj body 'fn)]))
(defn method-specs [sexprs]
(->> sexprs
(filter #(= 'method (first %)))
(mapcat method-spec)
(apply hash-map)))
(defn parent-class-spec [sexprs]
(let [extends-spec (filter #(= 'extends (first %)) sexprs)
extends (first extends-spec)]
(if (empty? extends)
'OBJECT
(last extends))))
(defmacro defclass [class-name & specs]
(let [parent-class (parent-class-spec specs)
fns (or (method-specs specs) {})]
`(def ~class-name (new-class '~class-name #'~parent-class ~fns))))
(defclass Person
(method age []
(* 2 10))
(method about [diff]
(str "I was born about " (+ diff (this :age)) " years ago")))
(defclass Woman
(extends Person)
(method greet [v]
(str "Hello, " v))
(method age []
(* 2 9)))
(def donna (Woman :new))
(donna :greet "Shelly")
(donna :age)
(donna :about 3)