Coverage report: /home/runner/work/geb/geb/src/mixins/package.lisp

KindCoveredAll%
expression013 0.0
branch00nil
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))
6
 
7
 (in-package :geb.mixins)
8
 
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
12
    project"
13
   (@pointwise      pax:section)
14
   (@pointwise-api  pax:section)
15
   (@mixin-examples pax:section)
16
   (@metadata       pax:section))
17
 
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"
21
   (cat-obj    pax:class)
22
   (cat-morph  pax:class)
23
   (dom        pax:generic-function)
24
   (codom      pax:generic-function)
25
   (curry-prod pax:generic-function))
26
 
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."
33
 
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)
37
 
38
   "For working with the structure it is best to have operations to treat
39
    it like an ordinary hashtable"
40
 
41
   (meta-insert pax:function)
42
   (meta-lookup pax:function)
43
 
44
   (@mixin-performance pax:section))
45
 
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.
49
 
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.
55
 
56
 The full layout can be observed from this interaction
57
 
58
 ```lisp
59
 ;; any class that uses the service
60
 (defparameter *x* (make-instance 'meta-mixin))
61
 
62
 (meta-insert *x* :a 3)
63
 
64
 (defparameter *y* (make-instance 'meta-mixin))
65
 
66
 (meta-insert *y* :b 3)
67
 
68
 (defparameter *z* (make-instance 'meta-mixin))
69
 
70
 ;; where {} is a hashtable
71
 {*x* {:a 3}
72
  *y* {:b 3}}
73
 ```
74
 
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
77
 
78
 ```lisp
79
 {*y* {:b 3}}
80
 ```
81
 
82
 for the hashtable.
83
 
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
86
 storage.")
87
 
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
98
    in our class"
99
   (direct-pointwise-mixin pax:class))
100
 
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)
112
 
113
   (pointwise-slots   pax:generic-function)
114
   (map-pointwise     pax:function)
115
   (reduce-pointwise  pax:function))
116
 
117
 (defun my-transcript (fn)
118
   (let ((pax:*transcribe-check-consistency*
119
           '((:readable obj-equalp))))
120
     (funcall fn)))
121
 
122
 (pax:defsection @mixin-examples (:title "Mixins Examples")
123
   "Let's see some example uses of POINTWISE-MIXIN:
124
 
125
   ```cl-transcript (:check-consistency ((:readable nil))) (:dynenv my-transcript)
126
   (obj-equalp (geb:terminal geb:so1)
127
               (geb:terminal geb:so1))
128
   => t
129
 
130
   (to-pointwise-list (geb:coprod geb:so1 geb:so1))
131
   => ((:MCAR . s-1) (:MCADR . s-1))
132
   ```")