-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnamespace-el.html
More file actions
496 lines (449 loc) · 36.4 KB
/
namespace-el.html
File metadata and controls
496 lines (449 loc) · 36.4 KB
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<!-- 2022-W11-4 02:12 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Namespaces in My Emacs? It's More Likely than you think!</title>
<meta name="author" content="Inanna" />
<meta name="description" content="Implementing namespaces and private in Emacs using lexical closures, lambdas, and macros." />
<meta name="generator" content="Org Mode" />
<link href="/site.css" rel="stylesheet" type="text/css" /><link href="images/website-icon.png" rel="icon" />
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
displayAlign: "center",
displayIndent: "0em",
"HTML-CSS": { scale: 100,
linebreaks: { automatic: "false" },
webFont: "TeX"
},
SVG: {scale: 100,
linebreaks: { automatic: "false" },
font: "TeX"},
NativeMML: {scale: 100},
TeX: { equationNumbers: {autoNumber: "AMS"},
MultLineWidth: "85%",
TagSide: "right",
TagIndent: ".8em"
}
});
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_HTML"></script>
</head>
<body>
<div id="preamble" class="status">
<div><a href="/index.html"><img alt="An abstract logo representing a series of three assembly line stamping machines with the words CONS, DEV, and embalzoned in white on each machine." id="site-logo" src="/images/website-logo.png" /></a></div>
</div>
<div id="content" class="content">
<h1 class="title">Namespaces in My Emacs? It's More Likely than you think!
<br />
<span class="subtitle">Implementing namespaces and private symbols using lexical closures.</span>
</h1>
<div id="table-of-contents" role="doc-toc">
<h2>Table of Contents</h2>
<div id="text-table-of-contents" role="doc-toc">
<ul>
<li><a href="#org7a6dd25">Key Findings</a></li>
<li><a href="#orgfc36785">Introduction</a></li>
<li><a href="#orgf63235e">Background</a></li>
<li><a href="#orgf219917">Implementation.</a></li>
<li><a href="#org0820ae2">Implementation</a>
<ul>
<li><a href="#org24a3ff8">The <code>ns</code> Macro</a></li>
<li><a href="#org571fcf4">Finding Private Definitions</a>
<ul>
<li><a href="#org4af966c">ns-find-private-refs</a></li>
<li><a href="#orgf00d561">ns-private?</a></li>
</ul>
</li>
<li><a href="#org16beb4f">Structure Transformers</a>
<ul>
<li><a href="#orgfce189f">ns-transform-private-refs</a></li>
<li><a href="#org46a27fa">ns-create-private-binds</a></li>
<li><a href="#orge8a6b98">ns-remove-private-defs</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#org8de356f">Limitations</a>
<ul>
<li><a href="#org168b58b">Lexical Binding Needs to be On</a></li>
<li><a href="#orgcfc3e89">Private Functions / Macros Cannot Be Called to Set Private Variables</a></li>
</ul>
</li>
<li><a href="#orgc6e8b70">Possible Improvements</a>
<ul>
<li><a href="#org3d89d9f">Making Lexical Binding Default</a></li>
<li><a href="#org02719e6">Higher Order Macros</a></li>
</ul>
</li>
<li><a href="#org7ddfc57">Further Thoughts</a>
<ul>
<li><a href="#org01db52b">Namespaces and Objects</a></li>
<li><a href="#orgbcc4d6d">Inheritance</a></li>
<li><a href="#org91210e7">Doing Without <code>let</code></a></li>
</ul>
</li>
</ul>
</div>
</div>
<div id="outline-container-org7a6dd25" class="outline-2">
<h2 id="org7a6dd25">Key Findings</h2>
<div class="outline-text-2" id="text-org7a6dd25">
<ul class="org-ul">
<li>It is possible to implement namespaces in Emacs Lisp through some hacks using lexical closures.</li>
</ul>
</div>
</div>
<div id="outline-container-orgfc36785" class="outline-2">
<h2 id="orgfc36785">Introduction</h2>
<div class="outline-text-2" id="text-orgfc36785">
<p>
Namespaces, a common.
</p>
</div>
</div>
<div id="outline-container-orgf63235e" class="outline-2">
<h2 id="orgf63235e">Background</h2>
<div class="outline-text-2" id="text-orgf63235e">
<p>
it's commonly said that Emacs does not have namespaces, everything is in one global mess of functions. This works because people create pseudo-namespaces by simply adding the name of the package onto the beginning of a function. This sadly leads to <i>really</i> long function names that can be an impediment to comprehension.
</p>
<p>
Lexical closures are a way to represent the structure
</p>
</div>
</div>
<div id="outline-container-orgf219917" class="outline-2">
<h2 id="orgf219917">Implementation.</h2>
<div class="outline-text-2" id="text-orgf219917">
<p>
But I realized while working on this blog <label class="sidenote-number" for="1"><sup>1</sup></label><input checked="checked" id="1" style="display:none" type="checkbox" /><span class="sidenote"><span class="sidenote-number"> 1</span> Specifically when using it to avoid polluting the global namespace <a href="source-code.html#org51ba0fe">here</a>.</span> that lexical binding and lexical closures were basically private functions and namespaces, if ugly looking. Therefore, if you just used something akin to this:
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #494949;">(</span><span style="color: #E53935; font-style: italic;">setq</span> lexical-binding t<span style="color: #494949;">)</span>
<span style="color: #494949;">(</span><span style="color: #E53935; font-style: italic;">let</span> <span style="color: #bbb;">(</span><span style="color: #494949;">(</span>fun <span style="color: #bbb;">(</span><span style="color: #E53935; font-style: italic;">lambda</span> <span style="color: #494949;">(</span>var<span style="color: #494949;">)</span> <span style="color: #494949;">(</span>+ var 23<span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span><span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span><span style="color: #E53935; font-style: italic;">defun</span> <span style="font-weight: bold; font-style: italic;">more-fun</span> <span style="color: #494949;">(</span>a<span style="color: #494949;">)</span>
<span style="color: #494949;">(</span>funcall fun a<span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
</pre>
</div>
<p>
You would discover that <code>fun</code> was no longer defined outside of the let binding, <i>however</i> (and this is the exciting part) <code>more-fun</code> would still add 23 to it's input because it had successfully captured <code>fun</code>!<label class="sidenote-number" for="2"><sup>2</sup></label><input checked="checked" id="2" style="display:none" type="checkbox" /><span class="sidenote"><span class="sidenote-number"> 2</span> This is very fun.</span>
</p>
<p>
So I began to wonder, what if I could <i>make</i> a namespace macro that solves this problem? The answer (obviously) is yes, though unfortunately it is still rather brittle due to the tenuous nature of lexical scoping in Emacs lisp. The implementation however was quick and allows you to take that code above and make it very readable:
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"> <span style="color: #494949;">(</span>ns more
<span style="color: #494949;">"An example for a really fun idea."</span>
<span style="color: #bbb;">(</span><span style="color: #E53935; font-style: italic;">defun</span> <span style="font-weight: bold; font-style: italic;">fun</span> <span style="color: #494949;">(</span>var<span style="color: #494949;">)</span> <span style="color: #494949;">(</span>+ var 23<span style="color: #494949;">)</span><span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span><span style="color: #E53935; font-style: italic;">defun</span> <span style="font-weight: bold; font-style: italic;">more-fun</span> <span style="color: #494949;">(</span>a<span style="color: #494949;">)</span>
<span style="color: #494949;">(</span>fun a<span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
</pre>
</div>
<p>
This is a much more natural way to write everything and, as implied, creates public functions based upon the inclusion of the namsepace symbol in the beginning of the function. This is pretty easy and the details of this implementation are provided <a href="#org571fcf4">here</a>.
</p>
<p>
I basically have to have the program walk the entire tree of all function calls and replace <code>(fun whatever)</code> with <code>(funcall fun whatever)</code>. This is not especially bad, but it does have to do it post macroexpansion and in \(O(n)\) time, which if you have very macro heavy code can be a pain.
</p>
<p>
After talking to some people about this I realized that this is similar to some of the concepts described in <i><a href="https://letoverlambda.com">Let Over Lambda</a></i>, a book on using lexical closures in macros for fun stuff like this. The upshot of that book
</p>
</div>
</div>
<div id="outline-container-org0820ae2" class="outline-2">
<h2 id="org0820ae2">Implementation</h2>
<div class="outline-text-2" id="text-org0820ae2">
<p>
The implementation is broken into a few helper functions and the macro. Because this is a demo (and not meant for RL code) I can use the helper functions since I can rely on them being expanded and loaded before the macro. However, if this were not a toy implementation then I would have to be fairly careful to ensure they are loaded in the proper order.
</p>
<p>
Regardless the algorithm for the transformations is fairly simple: first the system traverses the top level s-expressions in the namespace and first checks that they are in our list of "definitions".
</p>
<p>
Then the top level forms are macroexpanded fully and traversed in a depth first search, unquoting and replacing private function calls with <code>funcall</code> syntax. It is important to macroexpand the functions fully since they may contain features that are not properly called.
</p>
<p>
atomic
</p>
<p>
Following this process private symbols are "collected" in order and transformed into the let syntax which results in execution <i>mostly</i> equivalent to the previous state. Currently I use the <code>let</code> rather than <code>let*</code> for reasons discussed in the <a href="#orgcfc3e89">limitations</a> section.
</p>
</div>
<div id="outline-container-org24a3ff8" class="outline-3">
<h3 id="org24a3ff8">The <code>ns</code> Macro</h3>
<div class="outline-text-3" id="text-org24a3ff8">
<p>
This is the macro itself and
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><<ns-private?>>
<<ns-find-private-refs>>
<<ns-transform-private-refs>>
<<ns-create-private-binds>>
<<ns-remove-private-defs>>
<span style="color: #494949;">(</span><span style="color: #E53935; font-style: italic;">defmacro</span> <span style="font-weight: bold; font-style: italic;">ns</span> <span style="color: #bbb;">(</span>namespace <span style="color: #E53935;">&rest</span> forms-and-doc<span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span><span style="color: #E53935; font-style: italic;">declare</span> <span style="color: #494949;">(</span>doc-string 2<span style="color: #494949;">)</span>
<span style="color: #494949;">(</span>indent defun<span style="color: #494949;">)</span><span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span><span style="color: #E53935; font-style: italic;">let*</span> <span style="color: #494949;">(</span><span style="color: #bbb;">(</span>forms <span style="color: #494949;">(</span><span style="color: #E53935; font-style: italic;">if</span> <span style="color: #bbb;">(</span>eq <span style="color: #494949;">(</span><span style="color: #E53935; font-style: italic;">-></span> forms-and-doc first type-of<span style="color: #494949;">)</span> 'string<span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span>rest forms-and-doc<span style="color: #bbb;">)</span>
forms-and-doc<span style="color: #494949;">)</span><span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span>private-refs <span style="color: #494949;">(</span>ns-find-private-refs namespace forms<span style="color: #494949;">)</span><span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span>expanded-forms <span style="color: #494949;">(</span>-map 'macroexpand-all forms<span style="color: #494949;">)</span><span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span>transformed-forms <span style="color: #494949;">(</span>ns-transform-private-refs namespace private-refs expanded-forms<span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
`<span style="color: #494949;">(</span><span style="color: #E53935; font-style: italic;">progn</span>
<span style="color: #bbb;">(</span><span style="color: #E53935; font-style: italic;">setq</span> lexical-binding t<span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span><span style="color: #E53935; font-style: italic;">let</span> ,<span style="color: #494949;">(</span>ns-create-private-binds namespace transformed-forms<span style="color: #494949;">)</span>
,@<span style="color: #494949;">(</span>ns-remove-private-defs namespace transformed-forms<span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
</pre>
</div>
</div>
</div>
<div id="outline-container-org571fcf4" class="outline-3">
<h3 id="org571fcf4">Finding Private Definitions</h3>
<div class="outline-text-3" id="text-org571fcf4">
<p>
To start off everything we search for definitions, value setting, and other similar things to ensure the values are captured in the current namespace. Currently this is only done on the top level because dealing with internal functions gets rather irritating rather quickly. For the purposes of this definition search only <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Defining-Variables.html">defvar</a>, <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Defining-Variables.html">defconst</a>, <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Defining-Macros.html">defmacro</a>, defun, and defalias will be counted.
</p>
<p>
Now to make a symbol public you simply prefix it with the symbol used in the namespace. So to define a public function one might write:
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #494949;">(</span>ns namespaced
<span style="color: #494949;">"Another simple namespacing example."</span>
<span style="color: #bbb;">(</span><span style="color: #E53935; font-style: italic;">defun</span> <span style="font-weight: bold; font-style: italic;">private-fn</span> <span style="color: #494949;">(</span>a b<span style="color: #494949;">)</span> <span style="color: #494949;">(</span>+ a b<span style="color: #494949;">)</span><span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span><span style="color: #E53935; font-style: italic;">defun</span> <span style="font-weight: bold; font-style: italic;">namespaced-public-fn</span> <span style="color: #494949;">()</span> <span style="color: #494949;">(</span>private-fn 3 4<span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
</pre>
</div>
<p>
Thus we also filter out the definitions that begin with the same symbol as the namespace itself. This enforces a standardized approach to function naming and, as long as no two namespaces have the same name, eliminates the risk of name collisions.
</p>
</div>
<div id="outline-container-org4af966c" class="outline-4">
<h4 id="org4af966c">ns-find-private-refs</h4>
<div class="outline-text-4" id="text-org4af966c">
<p>
This filters the top level forms of the namespace using the <a href="#org5cf36a7">ns-private?</a> predicate function and then returns the list of all top level functions.
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp" id="org9d573ce"><span style="color: #494949;">(</span><span style="color: #E53935; font-style: italic;">defun</span> <span style="font-weight: bold; font-style: italic;">ns-find-private-refs</span> <span style="color: #bbb;">(</span>namespace forms<span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span><span style="color: #E53935; font-style: italic;">->></span> forms
<span style="color: #494949;">(</span>-filter <span style="color: #bbb;">(</span>-partial #'ns-private? namespace<span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
<span style="color: #494949;">(</span>-map 'second<span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
</pre>
</div>
<pre class="example">
ns-find-private-refs
</pre>
</div>
</div>
<div id="outline-container-orgf00d561" class="outline-4">
<h4 id="orgf00d561">ns-private?</h4>
<div class="outline-text-4" id="text-orgf00d561">
<p>
Here we define a small function that checks if our top level form is public. This simply grabs the first value of the form, then checks the second to see if it is the form has enough symbols to be a definition, then checks if it is top level or not.
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp" id="org5cf36a7"><span style="color: #494949;">(</span><span style="color: #E53935; font-style: italic;">defun</span> <span style="font-weight: bold; font-style: italic;">ns-private?</span> <span style="color: #bbb;">(</span>namespace top-level-form<span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span><span style="color: #E53935; font-style: italic;">let</span><span style="color: #494949;">(</span><span style="color: #bbb;">(</span>form-fun <span style="color: #494949;">(</span>first top-level-form<span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
<span style="color: #494949;">(</span><span style="color: #E53935; font-style: italic;">and</span> <span style="color: #bbb;">(</span>> <span style="color: #494949;">(</span>length top-level-form<span style="color: #494949;">)</span> 2<span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span>-contains?
<span style="color: #494949;">(</span>list 'defun 'defvar 'defmacro 'defconst 'defalias<span style="color: #494949;">)</span>
form-fun<span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span>not <span style="color: #494949;">(</span>s-matches? <span style="color: #bbb;">(</span>format <span style="color: #494949;">"%s-.*"</span> <span style="color: #494949;">(</span>symbol-name namespace<span style="color: #494949;">)</span><span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span>symbol-name <span style="color: #494949;">(</span><span style="color: #E53935; font-style: italic;">if</span> <span style="color: #bbb;">(</span>eq form-fun 'defalias<span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span>second <span style="color: #494949;">(</span>second top-level-form<span style="color: #494949;">)</span><span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span>second top-level-form<span style="color: #bbb;">)</span><span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-org16beb4f" class="outline-3">
<h3 id="org16beb4f">Structure Transformers</h3>
<div class="outline-text-3" id="text-org16beb4f">
<p>
Once we have a list of private definitions, we need to transform regular calls into the <code>funcall</code> syntax and unquote quoted names of our functions since our function symbols are actually variables. Now Emacs Lisp is a functional programming language, but the way the functions are defined is through the <code>fset</code> special form rather than simply setting a variable to a lambda, which gives their symbols a different syntax than that of a lambda simply bound to a symbol.
</p>
</div>
<div id="outline-container-orgfce189f" class="outline-4">
<h4 id="orgfce189f">ns-transform-private-refs</h4>
<div class="outline-text-4" id="text-orgfce189f">
<p>
This is a recursive function that conducts a depth first search of the tree created by the s-expressions, modifying them so that they are properly referred to as variables. It unfortunately has a lot of special cases / repeated structure which indicates to me that it is not as elegant as it could be, though I decided to not focus too much effort on refactoring it since this is both a toy example and irritatingly fragile code.
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp" id="orgcff7532"><span style="color: #494949;">(</span><span style="color: #E53935; font-style: italic;">defun</span> <span style="font-weight: bold; font-style: italic;">ns-transform-private-refs</span> <span style="color: #bbb;">(</span>namespace private-refs forms<span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span><span style="color: #E53935; font-style: italic;">cond</span> <span style="color: #494949;">(</span><span style="color: #bbb;">(</span>not <span style="color: #494949;">(</span>eq <span style="color: #bbb;">(</span>type-of forms<span style="color: #bbb;">)</span> 'cons<span style="color: #494949;">)</span><span style="color: #bbb;">)</span>
forms<span style="color: #494949;">)</span>
<span style="color: #494949;">(</span><span style="color: #bbb;">(</span><span style="color: #E53935; font-style: italic;">and</span> <span style="color: #494949;">(</span>eq <span style="color: #bbb;">(</span>first forms<span style="color: #bbb;">)</span> 'quote<span style="color: #494949;">)</span>
<span style="color: #494949;">(</span>-contains? private-refs <span style="color: #bbb;">(</span>second forms<span style="color: #bbb;">)</span><span style="color: #494949;">)</span><span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span>second forms<span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
<span style="color: #494949;">(</span><span style="color: #bbb;">(</span>eq <span style="color: #494949;">(</span>first forms<span style="color: #494949;">)</span> 'defalias<span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span>append
`<span style="color: #494949;">(</span>,<span style="color: #bbb;">(</span>first forms<span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
`<span style="color: #494949;">(</span>,<span style="color: #bbb;">(</span>second forms<span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
<span style="color: #494949;">(</span>-map <span style="color: #bbb;">(</span>-partial 'ns-transform-private-refs namespace private-refs<span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span>rest <span style="color: #494949;">(</span>rest forms<span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span><span style="color: #a4a4a4; font-style: italic;">;; </span><span style="color: #a4a4a4; font-style: italic;">avoid unquoting first form</span>
<span style="color: #494949;">(</span><span style="color: #bbb;">(</span>-contains? private-refs <span style="color: #494949;">(</span>first forms<span style="color: #494949;">)</span><span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span>-map <span style="color: #494949;">(</span>-partial 'ns-transform-private-refs namespace private-refs<span style="color: #494949;">)</span>
<span style="color: #494949;">(</span>cons 'funcall forms<span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
<span style="color: #494949;">(</span>t
<span style="color: #bbb;">(</span>-map <span style="color: #494949;">(</span>-partial 'ns-transform-private-refs namespace private-refs<span style="color: #494949;">)</span>
forms<span style="color: #bbb;">)</span><span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
</pre>
</div>
</div>
</div>
<div id="outline-container-org46a27fa" class="outline-4">
<h4 id="org46a27fa">ns-create-private-binds</h4>
<div class="outline-text-4" id="text-org46a27fa">
<p>
This transforms private bindings into a listing of symbols value two length lists as used by the <code>let</code> special form. The only tricky bit is pulling symbols from defalias.
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp" id="org089aa69"><span style="color: #494949;">(</span><span style="color: #E53935; font-style: italic;">defun</span> <span style="font-weight: bold; font-style: italic;">ns-create-private-binds</span> <span style="color: #bbb;">(</span>namespace forms<span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span><span style="color: #E53935; font-style: italic;">->></span> forms
<span style="color: #494949;">(</span>-filter <span style="color: #bbb;">(</span>-partial #'ns-private? namespace<span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
<span style="color: #494949;">(</span>-map <span style="color: #bbb;">(</span><span style="color: #E53935; font-style: italic;">lambda</span> <span style="color: #494949;">(</span>form<span style="color: #494949;">)</span>
<span style="color: #494949;">(</span><span style="color: #E53935; font-style: italic;">let</span> <span style="color: #bbb;">(</span><span style="color: #494949;">(</span>sym <span style="color: #bbb;">(</span><span style="color: #E53935; font-style: italic;">if</span> <span style="color: #494949;">(</span>eq <span style="color: #bbb;">(</span>first form<span style="color: #bbb;">)</span> 'defalias<span style="color: #494949;">)</span>
<span style="color: #494949;">(</span>second <span style="color: #bbb;">(</span>second form<span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
<span style="color: #494949;">(</span>second form<span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
<span style="color: #494949;">(</span>val <span style="color: #bbb;">(</span>third form<span style="color: #bbb;">)</span><span style="color: #494949;">)</span><span style="color: #bbb;">)</span>
`<span style="color: #bbb;">(</span>,sym ,val<span style="color: #bbb;">)</span><span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
</pre>
</div>
</div>
</div>
<div id="outline-container-orge8a6b98" class="outline-4">
<h4 id="orge8a6b98">ns-remove-private-defs</h4>
<div class="outline-text-4" id="text-orge8a6b98">
<p>
This removes the private references from the list that is located in the public portion of the <code>let</code> special form, preventing their definition in the global lexical scope.
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp" id="orgbbaeec8"><span style="color: #494949;">(</span><span style="color: #E53935; font-style: italic;">defun</span> <span style="font-weight: bold; font-style: italic;">ns-remove-private-defs</span> <span style="color: #bbb;">(</span>namespace forms<span style="color: #bbb;">)</span>
<span style="color: #bbb;">(</span>-filter <span style="color: #494949;">(</span><span style="color: #E53935; font-style: italic;">lambda</span> <span style="color: #bbb;">(</span>form<span style="color: #bbb;">)</span> <span style="color: #bbb;">(</span>not <span style="color: #494949;">(</span>ns-private? namespace form<span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span> forms<span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
</pre>
</div>
</div>
</div>
</div>
</div>
<div id="outline-container-org8de356f" class="outline-2">
<h2 id="org8de356f">Limitations</h2>
<div class="outline-text-2" id="text-org8de356f">
</div>
<div id="outline-container-org168b58b" class="outline-3">
<h3 id="org168b58b">Lexical Binding Needs to be On</h3>
<div class="outline-text-3" id="text-org168b58b">
<p>
Lexical binding is not active by default and is buffer-local. This is actually pretty bad as it basically causes the lexical closures to suddenly disappear in a puff of smoke. I could use the <code>lexical-let</code> or <code>lexical-let*</code> functions in the <code>cl</code> library, which would solve the problem, though they are specified as being deprecated.
</p>
</div>
</div>
<div id="outline-container-orgcfc3e89" class="outline-3">
<h3 id="orgcfc3e89">Private Functions / Macros Cannot Be Called to Set Private Variables</h3>
<div class="outline-text-3" id="text-orgcfc3e89">
<p>
Unfortunately, because the <code>let*</code> special form does not produce lexical closures even with <code>lexical-binding</code> set to <code>t</code>, I cannot effectively use it. This means that all <code>let</code> forms are bound at the same time (rather than sequentially) and therefore cannot be called to set private variables or generate private code.
</p>
<p>
I could write my own <code>let*</code> replacement to bind them sequentially, which would work though also be a bit inelegant and be working around what I <i>think</i> is a bug in Emacs itself (which is therefore something that ought to be fixed in the C source code, not hacked around).
</p>
</div>
</div>
</div>
<div id="outline-container-orgc6e8b70" class="outline-2">
<h2 id="orgc6e8b70">Possible Improvements</h2>
<div class="outline-text-2" id="text-orgc6e8b70">
<p>
Though it does show that Emacs has the fundamental components needed for private variables / functions already I think that some improvements could be made, namely the addition of the ability to import namespaces. I also might want to think beyond namespaces and look at implementing something altogether more general (though I don't want to simply write another object system for Emacs).
</p>
</div>
<div id="outline-container-org3d89d9f" class="outline-3">
<h3 id="org3d89d9f">Making Lexical Binding Default</h3>
<div class="outline-text-3" id="text-org3d89d9f">
<p>
There is also a major issue when dealing with code without lexical binding as in those cases the functions suddenly break as they are no longer lexical closures, and since <code>lexical-binding</code> is buffer-local, that kind of messes up a lot of code. Therefore I think the next step is to take a deep dive into Emacs Lisp code and look at how I could make lexical binding the default for all new files and the user environment.
</p>
</div>
</div>
<div id="outline-container-org02719e6" class="outline-3">
<h3 id="org02719e6">Higher Order Macros</h3>
<div class="outline-text-3" id="text-org02719e6">
<p>
Another interesting possibility with namespaces is to drop the whole lexical closure thing instead make them macros that provide access to a list of lambdas indexed by the symbol provided. So for example:
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #494949;">(</span>ns foo
<span style="color: #bbb;">(</span><span style="color: #E53935; font-style: italic;">defun</span> <span style="font-weight: bold; font-style: italic;">bar</span> <span style="color: #494949;">(</span>a<span style="color: #494949;">)</span> <span style="color: #494949;">(</span>! <span style="color: #bbb;">(</span>+ a 3<span style="color: #bbb;">)</span><span style="color: #494949;">)</span><span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
</pre>
</div>
<p>
Would produce a macro called "foo" that would, depending on it's arguments, expand to a variety of different functions. Then you could call the functions in it like so:
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #494949;">(</span>foo bar 33<span style="color: #494949;">)</span>
</pre>
</div>
<p>
You could also alias that function using the namespace macros produced, which would make it intuitive to directly use your functions in the new namespace while also not requiring lexical scoping.
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #494949;">(</span><span style="color: #E53935; font-style: italic;">defalias</span> <span style="color: #bbb;">(</span>foo bar<span style="color: #bbb;">)</span><span style="color: #494949;">)</span>
</pre>
</div>
<p>
I might try it out sometime soon and will link to the blog post, regardless of how successful the implementation is.
</p>
</div>
</div>
</div>
<div id="outline-container-org7ddfc57" class="outline-2">
<h2 id="org7ddfc57">Further Thoughts</h2>
<div class="outline-text-2" id="text-org7ddfc57">
</div>
<div id="outline-container-org01db52b" class="outline-3">
<h3 id="org01db52b">Namespaces and Objects</h3>
<div class="outline-text-3" id="text-org01db52b">
<p>
One interesting thing that I found while implementing this is that namespaces are in essence singlton static classes, and that it is really more proper to say that classes are the general case of namespaces. This actually makes me respect the python approach to namespaces a little more.
</p>
<p>
However, I think the affordances of namespaces and classes are rather different, producing different outcomes in terms of software design. Classes make it easy to envision coupling state with data (sort of like closures), but encourage it rather strongly, often being seen as a extension of the <code>struct</code> concept in C.
</p>
<p>
Namespaces however, do not obviously make it so that you can couple state and data even if you can use them as singleton classes. Therefore one is inclined to approach them from a more functional perspective.
</p>
</div>
</div>
<div id="outline-container-orgbcc4d6d" class="outline-3">
<h3 id="orgbcc4d6d">Inheritance</h3>
<div class="outline-text-3" id="text-orgbcc4d6d">
<p>
It also became apparent that you can fairly easily implement all object oriented programming concepts including inheritance (contrary as to what is implied with <i>Let Over Lambda</i>) with lexical closures and lambdas. One simply makes it such that the closure will evaluate another closure within it's environment and then returns that closure, creating a sort of tower of lexical closures.
</p>
</div>
</div>
<div id="outline-container-org91210e7" class="outline-3">
<h3 id="org91210e7">Doing Without <code>let</code></h3>
<div class="outline-text-3" id="text-org91210e7">
<p>
It is possible to do this all without let, assuming you permit a modification of how <code>lambda</code> works. Instead of having <code>lambda</code> merely producing an anonymous function, imagine if it creates a new lexical scope and that a <code>set</code> function exists that can bind variables within that scope. Using this it is trivial to construct a <code>let</code> function using <code>set</code> and <code>lambda</code> alone. This has pretty much no practical application, though I thought the idea was somewhat cool.
</p>
</div>
</div>
</div>
<!-- Footnotes --><!--
<div class="footdef"><sup><a id="fn.1" class="footnum" href="#fnr.1" role="doc-backlink">1</a></sup> <div class="footpara" role="doc-footnote"><p class="footpara">Specifically when using it to avoid polluting the global namespace <a href="source-code.html#org51ba0fe">here</a>.</p></div></div>
<div class="footdef"><sup><a id="fn.2" class="footnum" href="#fnr.2" role="doc-backlink">2</a></sup> <div class="footpara" role="doc-footnote"><p class="footpara">This is very fun.</p></div></div>
--></div>
<div id="postamble" class="status">
<p class="date">Last Modified: 2022-W11-4 01:21</p><p class="creator">Generated Using: <a href="https://www.gnu.org/software/emacs/">Emacs</a> 27.2 (<a href="https://orgmode.org">Org</a> mode 9.4.6)</p><p class="license">Except where otherwise noted content on <a href="https://cons.dev">cons.dev</a> is licensed under a <a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license">Creative Commons Attribution-ShareAlike 4.0 International License</a>.</p>
</div>
</body>
</html>