270
R. Hamers and S.-S. Jongmans
1 (def def def blank " ") (def def def cross "x") (def def def nought "o")
2
3 (def def def initial-grid [blank blank blank
;; an initial 3x3 grid of blank spaces,
4
blank blank blank
;; implemented as a vector of length 9
5
blank blank blank]) ;; (persistent data structure)
6
7 (def def def get-blank (fn fn fn [g]
...)) ;; returns a blank space in g
8 (def def def add
(fn fn fn [g i x-or-o] ...)) ;; returns g, but with i set to x-or-o
9 (def def def not-final? (fn fn fn [g]
...)) ;; returns true iff g is not final
10
11 (def def def a->b (chan chan chan 1)) (def def def b<-a a->b) ;; b<-a is an alias of a->b
12 (def def def b->a (chan chan chan 1)) (def def def a<-b b->a) ;; a<-b is an alias of b->a
13
14 (thread thread thread ;; alice
15
(loop loop loop [g initial-grid]
16
(let let let [i (get-blank g)
17
g (set g i cross)]
18
(>!! >!! >!! a->b i)
19
(if if if (not-final? g)
20
(let let let [i ( 21
g (set g i nought)]
22
(if if if (not-final? g)
23
(recur recur recur g))))))
24
(close! close! close! a->b))
25 (thread thread thread ;; bob
26
(loop loop loop [g initial-grid]
27
(let let let [i ( 28
g (set g i cross)]
29
(if if if (not-final? g)
30
(let let let [i (get-blank g)
31
g (set g i nought)]
32
(>!! >!! >!! b->a i)
33
(if if if (not-final? g)
34
(recur recur recur g))))))
35
(close! close! close! b->a))
Fig. 3. Clojure implementation of Tic-Tac-Toe (dashed arrows: matching send/receive)
Library clojure.core (basic):
– (def def def x e): first evaluates e to v; then binds x to v in the global environment.
– (fn fn fn [x 1 ... xn] e1 ... em): evaluates to a function with parameters x1, ...,
xn and creates a recursion point; then, when applied to arguments v1, ..., vn,
sequentially evaluates e1, ..., em with x1, ..., xn bound to v1, ..., vn.
– (let let let [x1 e1 ... xn en] e): first evaluates e1 to v1; then evaluates e2 to v2
with x1 bound to v1; ...; then evaluates en to vn with x1, ..., xn−1 bound to v1,
..., vn−1; then evaluates e with x1, ..., xn bound to v1, ..., vn.
– (loop loop loop [x1 e1 ... xn en] e): same as let let let, but also creates a recursion point.
– (recur recur recur e1 ... en): first evaluates e1, ..., en to v1, ..., vn; then evaluates the
nearest recursion point with x1, ..., xn bound to v1, ..., vn.
– (if if if e1 e2 e3): first evaluates e1; if true, evaluates e2; else, evaluates e3.
Library clojure.core.async (concurrency):
– (>!! >!! >!! c e): first evaluates e to v; then sends v through channel c.
– ( – (close! close! close! c): closes channel c.
– (chan chan chan n): evaluates to a channel with a buffer of size n.
– (thread thread thread e): creates a new thread that evaluates e
Fig. 4. Clojure primitives
Précédent

- 287/515

Suivant