2 \documentclass{article
}
3 \input{arxana-header.tex
}
8 \author{Joseph Corneli \& Raymond Puzio
\thanks{Copyright (C)
2017
9 Joseph Corneli
{\tt <holtzermann17@gmail.com>
}\newline
10 Copyright (C)
2017 Raymond Puzio
{\tt <rsp@planetmath.info>
}}}
11 \date{Last revised:
\today}
15 \abstract{This is a reference implementation of arxana backend
16 primitives as described in the honey spec.
}
20 \section{Introduction
}
22 \begin{notate
}{What we are doing?
}
23 Here we present a purely functional implementation of nemata and
24 plexi as s-expressions. To make everything explict, we pass the
25 plexus as an argument to to our functions and, in the case of
26 functions that can modify it, get the plexus back in the output.
28 In order to make for a reader-friendly exposition we will develop
29 our code incrementally. Since it is meant primarily to illustrate
30 principles, the first version of the code presented here will
31 hopelessly clunky and inefficient. In successive versions, we will
32 make various opimizations and improvements until we arrive at a more
33 practical implementation.
36 \begin{notate
}{Theoretical definition
}
37 We begin with a theoretical definition of a plexus as quintuplet $(U,
41 \item $U$ is a (finite) set of identifiers
42 \item $G$ is a distinguished element of $U$. (the ground)
43 \item $H$ and $T$ are functions from $U$ to $U$ (head and tail)
44 \item $C$ is a function from $U$ to a content set $S$
47 subject to the conditions that $H(G) = T(G) = G$.
49 By using the canonical isomorphism between a set of functions with a
50 common domain and a single function from the same domain to the
51 product of their codomains, we may rewrite the definition as a
52 triplet $(U, G, N)$ where $N$ is a function from $U$ to $H
\times T
53 \times C$. The graph of $N$ consists of a set of quartiplets, which
56 For the purpose of implementing this structure in LISP, we will take
57 the identifiers which lie in $U$ to be natural numbers, take $G$ to
58 be
0, and take the content set $S$ to be the set of LISP lists. We
59 will represent a nema by cons'ing an element $x$ of $U$ and the
60 corresponding values $H(x)$ and $T(x)$ onto $C(x)$. Since we fixed
61 the value of $G$ once and for all, we don't have to restate it, so a
62 plexus will be represented as a list whose
\verb|car| is $U$ and
63 whose
\verb|cdr| is the association list of nemata.
68 \begin{notate
}{About version
0}
69 The honey primitives can be described as mathematical functions on
70 the structure described above. We will now write down these
71 functions explicitly and translate the mathematical notation into
72 LISP to produce the initial version.
75 \subsection{Utility routines
}
77 \begin{notate
}{Why utilities?
}
78 Before starting, we need to defun a few simple utility functions.
79 Adhering to the highest standards of purity, we write them
80 recursively and immutably.
83 \begin{notate
}{On `next-available-number'
}
84 The first function takes a set of integers and a starting number
85 finds the smallest integer which is not in the list but above the
86 starting point. This will be used to generate identifiers when
90 (defun next-available-number (ids start)
91 (if (member start ids)
92 (next-available-number ids (+ start
1))
96 \begin{notate
}{On `filter'
}
97 Select out the elements of the list which satisfy the predicate.
100 (defun filter (prd lis)
102 (if (funcall prd (car lis))
104 (filter prd (cdr lis)))
105 (filter prd (cdr lis)))
109 \begin{notate
}{On `cons*'
}
110 Convenience function which
\verb|cons|'es a whole bunch of stuff in
111 front of a list. This could just as well be done as
112 \verb(append (list ... ))
\verb but since we will be doing this
113 fairly often, it tidies up the code to give it a name.
116 (defun cons* (&rest args)
119 (apply 'cons* (cdr args)))
123 \subsection{Individual Operations
}
125 \begin{notate
}{On `add-nema'
}
126 Formally, we may define $
\mathrm{add-nema
} :
\mathbf{Plex
} \times
127 \mathbb{N
} \times \mathbb{N
} \times S
\to \mathbf{Plex
}$ as
128 $((U, G, H, T, C), h, t, c)
\mapsto (U' G' H' T' C')$
131 U' &= \
{0\
} \sqcup U \\
132 G' &=
\mathrm{in
}_2 (G) \\
133 H'
\circ \mathrm{in
}_2 &= H, & H'(
\mathrm{in
}_1(
0)) &= h \\
134 T'
\circ \mathrm{in
}_2 &= T, & T'(
\mathrm{in
}_1(
0)) &= t \\
135 C'
\circ \mathrm{in
}_2 &= C, & C'(
\mathrm{in
}_1(
0)) &= c .
137 We will implement the coproduct with a singleton by picking a number
138 which is not in $U$ and consing it on to $U$. Then $
\mathrm{in
}_2$
139 is just restriction of $U'$ to $U$ so all we need to do is add a
143 (defun pure-add-nema-v0 (plex src txt snk)
144 (let ((next (next-available-number (car plex)
1)))
147 (cons next (car plex))
148 ;; then the the new nema
149 (cons* next src snk txt)))
150 ;; and end with the old nemata.
154 \begin{notate
}{On `remove-nema'
}
155 Formally, we may define
157 \mathtt{remove
{\mhyphen}nema
} :
\prod_{p
158 \colon \mathbf{Plex
}} \mathrm{pr
}_1 (p)
\setminus \
{ \mathrm{pr
}_2
159 (p) \
} &
\to \mathbf{Plex
} \\
160 ((U, G, H, T, C), n) &
\mapsto (U', G, H
161 |_
{U'
}, T |_
{U'
}, C |_
{U'
})
163 where $U' = U
\setminus \
{n\
}$.
166 (defun pure-remove-nema-v0 (plex nema)
168 (remove nema (car plex))
169 (remove (assoc nema (cdr plex))
173 \begin{notate
}{On `get-src', `get-sink' and `get-content'
}
176 \mathrm{get-source
} \colon
177 \prod_{p
\colon \mathbf{Plex
}} \mathrm{pr
}_1(p) &
\to \mathbb{N
} \\
178 ((U, G, H, T, C), n) &
\mapsto H(n) \\
179 \mathrm{get-sink
} \colon
180 \prod_{p
\colon \mathbf{Plex
}} \mathrm{pr
}_1(p) &
\to \mathbb{N
} \\
181 ((U, G, H, T, C), n) &
\mapsto T(n) \\
182 \mathrm{get-content
} \colon
183 \prod_{p
\colon \mathbf{Plex
}} \mathrm{pr
}_1(p) &
\to S \\
184 ((U, G, H, T, C), n) &
\mapsto C(n)
186 Woo-hoo, dependent types!!
189 (defun pure-get-source-v0 (plex nema)
190 (nthcdr
1 (assoc nema (cdr plex))))
192 (defun pure-get-sink-v0 (plex nema)
193 (nthcdr
2 (assoc nema (cdr plex))))
195 (defun pure-get-content-v0 (plex nema)
196 (nthcdr
3 (assoc nema (cdr plex))))
199 \begin{notate
}{On `get-forward-links' and `get-backward-links'
}
202 \mathrm{get-forward-links
} \colon
203 \prod_{p :
\mathbf{Plex
}} \mathrm{pr
}_1(p) &
\to
204 \mathcal{P
}(
\mathbb{Z
}) \\
205 ((U, G, H, T, C), n) &
\mapsto H^
{-
1} (n) \\
206 \mathrm{get-backward-links
} :
207 \prod_{p :
\mathbf{Plex
}} \mathrm{pr
}_1(p) &
\to
208 \mathcal{P
}(
\mathbb{Z
}) \\
209 ((U, G, H, T, C) n) &
\mapsto T^
{-
1} (n) .
213 (defun pure-get-forward-links-v0 (plex nema)
215 (filter (lambda (x) (equal x (nth
1 nema)))
218 (defun pure-get-backward-links-v0 (plex nema)
220 (filter (lambda (x) (equal x (nth
2 nema)))
224 \begin{notate
}{On `update-source', `update-sink', and
226 Formally, we have the following:
228 \mathtt{update-source
} :
229 \prod_{p :
\mathbf{Plex
}}
230 \mathrm{pr
}_1(p)
\times \mathrm{pr
}_1(p)
231 &
\to \mathbf{Plex
} \\
232 ((U, G, H, T, C), n, m) &
\mapsto (U, G, H', T, C)
234 where $H'(k) = H(k)$ when $k
\neq n$ and $H'(n) = m$.
236 \mathtt{update-sink
} :
237 \prod_{p :
\mathbf{Plex
}}
238 \mathrm{pr
}_1(p)
\times \mathrm{pr
}_1(p)
239 &
\to \mathbf{Plex
} \\
240 ((U, G, H, T, C), n, m) &
\mapsto (U, G, H, T', C)
242 where $T'(k) = T(k)$ when $k
\neq n$ and $T'(n) = m$.
244 \mathtt{update-source
} :
245 \prod_{p :
\mathbf{Plex
}}
246 \mathrm{pr
}_1(p)
\times S
247 &
\to \mathbf{Plex
} \\
248 ((U, G, H, T, C), n, m) &
\mapsto (U, G, H, T, C')
250 where $C'(k) = C(k)$ when $k
\neq n$ and $C'(n) = m$.
254 (defun update-source (plex nema new-src)
255 (let ((changer (assoc nema (cdr plex))))
259 ;; The nema with an updated source.
265 ;; The rest of the nemata which remain unchanged.
266 (remove changer (cdr plex)))))
268 (defun update-sink (plex nema new-snk)
269 (let ((changer (assoc nema (cdr plex))))
273 ;; The nema with an updated sink.
279 ;; The rest of the nemata which remain unchanged.
280 (remove changer (cdr plex)))))
282 (defun update-content (plex nema txt)
283 (let ((changer (assoc nema (cdr plex))))
287 ;; The nema with a updated content.
293 ;; The rest of the nemata which remain unchanged.
294 (remove changer (cdr plex)))))