-
Notifications
You must be signed in to change notification settings - Fork 42
/
box.lisp
63 lines (50 loc) · 1.75 KB
/
box.lisp
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
(in-package #:serapeum)
(eval-when (:compile-toplevel :load-toplevel :execute)
(defconstant +atomic-accessors+
(and (member :ecl *features*)
(ignore-errors
(eval `(defstruct (,(gensym) :atomic-accessors))))
'(:atomic-accessors))))
(declaim (inline box)) ;Allow dynamic-extent.
(defstruct (box (:constructor box (unbox))
(:predicate boxp)
(:conc-name nil)
;; Required for older ECLs only.
. #.+atomic-accessors+)
"A box is just a mutable cell.
You create a box using `box' and get and set its value using the
accessor `unbox'.
(def a-box (box t))
(unbox a-box) => t
(setf (unbox a-box) nil)
(unbox a-box) => nil
Serapeum attempts to provide the guarantee that, on Lisps that support
atomic operations (compare-and-swap), `unbox` on boxes should be
updateable atomically. (See
[atomics](https://github.com/Shinmera/atomics))."
unbox)
(declaim-freeze-type box)
(setf (documentation 'box 'function)
"Box a value.")
(setf (documentation 'unbox 'function)
"The value in the box X."
(documentation '(setf unbox) 'function)
"Put VALUE in box X.")
(defmethod print-object ((self box) stream)
(print-unreadable-object (self stream :type t :identity t)
(format stream "~a" (unbox self)))
self)
(defmethod make-load-form ((self box) &optional env)
(declare (ignore env))
(values `(box)
`(setf (unbox ',self) ,(unbox self))))
(defpattern box (x)
(with-unique-names (b)
`(trivia:guard1 ,b
(typep ,b 'box)
(unbox ,b)
,x)))
(-> ensure-box (t) box)
(defun ensure-box (x)
"Return X if boxed, otherwise a box containing X."
(if (boxp x) x (box x)))