Coverage report: /home/runner/work/geb/geb/src/mixins/package.lisp
Kind | Covered | All | % |
expression | 0 | 13 | 0.0 |
branch | 0 | 0 | nil |
Key
Not instrumented
Conditionalized out
Executed
Not executed
Both branches taken
One branch taken
Neither branch taken
1
(pax:define-package :geb.mixins
2
(:documentation "Package defines various useful mixins")
3
(:local-nicknames (:util :geb.utils))
4
(:use #:serapeum #:common-lisp)
5
(:export #:@mixins #:@mixins-cat #:@metadata))
7
(in-package :geb.mixins)
9
(pax:defsection @mixins (:title "Mixins" :export t)
10
"Various [mixins](https://en.wikipedia.org/wiki/Mixin) of the
11
project. Overall all these offer various services to the rest of the
13
(@pointwise pax:section)
14
(@pointwise-api pax:section)
15
(@mixin-examples pax:section)
16
(@metadata pax:section))
18
(pax:defsection @mixins-cat (:title "The Categorical Interface")
19
"This covers the main Categorical interface required to be used and
20
contained in various data structures"
23
(dom pax:generic-function)
24
(codom pax:generic-function)
25
(curry-prod pax:generic-function))
27
(pax:defsection @metadata (:title "Metadata Mixin")
28
"Metadata is a form of meta information about a particular
29
object. Having metadata about an object may be useful if the goal
30
requires annotating some data with type information, identification
31
information, or even various levels of compiler information. The
32
possibilities are endless and are a standard technique."
34
"For this task we offer the [META-MIXIN][class] which will allow
35
metadata to be stored for any type that uses its service."
36
(meta-mixin pax:class)
38
"For working with the structure it is best to have operations to treat
39
it like an ordinary hashtable"
41
(meta-insert pax:function)
42
(meta-lookup pax:function)
44
(@mixin-performance pax:section))
46
(pax:defsection @mixin-performance (:title "Performance")
47
"The data stored is at the CLASS level. So having your type take the
48
[META-MIXIN][class] does interfere with the cache.
50
Due to concerns about meta information being populated over time, the
51
table which it is stored with is in a
52
[weak](http://www.lispworks.com/documentation/lcl50/aug/aug-141.html)
53
hashtable, so if the object that the metadata is about gets
54
deallocated, so does the metadata table.
56
The full layout can be observed from this interaction
59
;; any class that uses the service
60
(defparameter *x* (make-instance 'meta-mixin))
62
(meta-insert *x* :a 3)
64
(defparameter *y* (make-instance 'meta-mixin))
66
(meta-insert *y* :b 3)
68
(defparameter *z* (make-instance 'meta-mixin))
70
;; where {} is a hashtable
75
Since `*z*` does not interact with storage no overhead of storage is
76
had. Further if `*x* goes out of scope, gc would reclaim the table leaving
84
Even the tables inside each object's map are weak, thus we can make
85
storage inside metadata be separated into volatile and stable
88
(pax:defsection @pointwise (:title "Pointwise Mixins")
89
"Here we provide various mixins that deal with classes in a pointwise
90
manner. Normally, objects can not be compared in a pointwise manner,
91
instead instances are compared. This makes functional idioms like
92
updating a slot in a pure manner (allocating a new object), or even
93
checking if two objects are `EQUAL`-able adhoc. The pointwise API,
94
however, derives the behavior and naturally allows such idioms"
95
(pointwise-mixin pax:class)
96
"Further we may wish to hide any values inherited from our superclass
97
due to this we can instead compare only the slots defined directly
99
(direct-pointwise-mixin pax:class))
101
(pax:defsection @pointwise-API (:title "Pointwise API")
102
"These are the general API functions on any class that have the
103
POINTWISE-MIXIN service."
104
"Functions like TO-POINTWISE-LIST allow generic list traversal APIs to
105
be built off the key-value pair of the raw object form, while
106
OBJ-EQUALP allows the checking of functional equality between
107
objects. Overall the API is focused on allowing more generic
108
operations on classes that make them as useful for generic data
109
traversal as `LIST`'s are"
110
(to-pointwise-list pax:generic-function)
111
(obj-equalp pax:generic-function)
113
(pointwise-slots pax:generic-function)
114
(map-pointwise pax:function)
115
(reduce-pointwise pax:function))
117
(defun my-transcript (fn)
118
(let ((pax:*transcribe-check-consistency*
119
'((:readable obj-equalp))))
122
(pax:defsection @mixin-examples (:title "Mixins Examples")
123
"Let's see some example uses of POINTWISE-MIXIN:
125
```cl-transcript (:check-consistency ((:readable nil))) (:dynenv my-transcript)
126
(obj-equalp (geb:terminal geb:so1)
127
(geb:terminal geb:so1))
130
(to-pointwise-list (geb:coprod geb:so1 geb:so1))
131
=> ((:MCAR . s-1) (:MCADR . s-1))