-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsrfi-260.html
191 lines (151 loc) · 8.81 KB
/
srfi-260.html
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
<!DOCTYPE html>
<html lang="en">
<!--
SPDX-FileCopyrightText: 2025 Marc Nieper-Wißkirchen
SPDX-License-Identifier: MIT
-->
<head>
<meta charset="utf-8">
<title>SRFI 260: Generated Symbols</title>
<link href="/favicon.png" rel="icon" sizes="192x192" type="image/png">
<link rel="stylesheet" href="https://srfi.schemers.org/srfi.css" type="text/css">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>span.nobr { white-space: nowrap; }</style></head>
<body>
<h1><a href="https://srfi.schemers.org/"><img class="srfi-logo" src="https://srfi.schemers.org/srfi-logo.svg" alt="SRFI surfboard logo" /></a>260: Generated Symbols</h1>
<p>by Marc Nieper-Wißkirchen</p>
<h2 id="status">Status</h2>
<p>This SRFI is currently in <em>draft</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+260+at+srfi+dotschemers+dot+org">srfi-260@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-260/">archive</a>.</p>
<ul>
<li>Received: 2025-01-27</li>
<li>60-day deadline: 2025-03-28</li>
<li>Marc's <a href="https://github.com/mnieper/gensyms">personal
Git repo for this SRFI</a> for reference while the SRFI is in
<em>draft</em> status (<a href="https://htmlpreview.github.io/?https://github.com/mnieper/gensyms/blob/main/srfi-XXX.html">preview</a>)</li>
<li>Draft #1 published: 2025-01-27</li>
</ul>
<h2 id="abstract">Abstract</h2>
<p>This SRFI defines the procedure <code>generate-symbol</code>. Each
time it is invoked, the procedure returns a new symbol whose name
cannot be guessed. The returned symbol is a standard symbol for all
purposes; it obeys write/read invariance and it is equal to another
symbol if and only if their names are spelt the same.</p>
<h2 id="issues">Issues</h2>
<p>None at present.</p>
<h2 id="rationale">Rationale</h2>
<p>A <dfn>unique object</dfn> is a Scheme value that is not equal
(usually with respect to <code>eqv?</code>) to existing (or potentially
existing) objects. Unique objects have many use cases, for example as
private keys in data structures or to uniquely mark other values.</p>
<p>Scheme has many ways to create such unique objects. For many
purposes, an expression like <code>(string #\m)</code> can be used to
create a unique object. To improve type safety, alternatively, a
constructor of a record type with at least one mutable field can be
invoked.</p>
<p>There are circumstances where such unique objects, may they be
strings or records, cannot be used because an object of a particular
type, specifically a symbol, is needed. In the case of Scheme, this
applies to its syntax system. An identifier is a syntax object that is
a wrapped symbol
(see <a href="https://www.r6rs.org/">R<sup>6</sup>RS</a>). To
generate unique identifiers with a given wrap, unique symbols (and not
strings, records, etc.), therefore, have to be generated.</p>
<p>The procedure <code>generate-symbol</code> defined in this SRFI
provides a means to generate unique symbols.</p>
<p>Alternative proposals
like <a href="https://srfi.schemers.org/srfi-258/srfi-258.html">SRFI
258</a> provide so-called uninterned symbols that can also be used for
this purpose (at least after amending the definition of a syntax
object). Introducing uninterned symbols into the standard, however,
would weaken the semantics of symbols. Two symbols would no longer be
identical (in the sense of <code>eqv?</code>) if and only if their
names are spelt the same way.</p>
<p>Uninterned symbols have another disadvantage in that they defeat
write/read invariance. Yet, some kind of write/read invariance is
likely needed when uninterned symbols are used in identifier names so
that expanded Scheme code can be serialised (e.g. for separate AOT
expansion/compilation).</p>
<p>As names for generated symbols can be generated lazily, the alleged
advantage of uninterned symbols — that no names have to be generated — is
a bogus one. A name for a generated symbol only has to be generated
for use cases that need the unique name
from <code><span class="nobr">symbol->string</span></code>, e.g. for write/read purposes, but
these use cases are not covered by uninterned symbols anyway.</p>
<p>Generated symbols need no new lexical syntax. The notion of a
Scheme datum value does not change; a Scheme datum value remains a
Scheme value that obeys write/read equivalence (up
to <code>equal?</code>).</p>
<h2 id="specification">Specification</h2>
<h3>Libraries</h3>
<p>The following binding is exported by the <code>(srfi :260 generate-symbol)</code> library:</p>
<p><u>Procedure:</u> <code><b>generate-symbol</b></code> [<var>pretty-name</var>]
<p>The optional argument, <var>pretty-name</var>, must, if present, be a string.</p>
<p>Returns a symbol that is not identical to any existing or
potentially existing symbol, for all practical purposes.</p>
<p><i>Note:</i> This means that for every Scheme
expression <code>⟨expression⟩</code> whose (possibly
non-deterministic) value does not depend on the result
of <code>symbol->string</code> applied to the
result <var>gensym</var> of a previous invocation
of <code>generate-symbol</code>, its value is not equal (in the sense
of <code>equal?</code>) to the value
of <code>(symbol->string</code> <var>gensym</var><code>)</code> for
all practical purposes.</p>
<p>The implementation may use the argument <var>pretty-name</var> for debugging or pretty-printing purposes.</p>
<pre>(let ([s (generate-symbol)])
(symbol=? s s)) ; => #t</pre>
<pre>(let ([s1 (generate-symbol)] [s2 (generate-symbol)])
(symbol=? s1 s2)) ;=> #f</pre>
<pre>(let ([s1 (generate-symbol "g1")] [s2 (generate-symbol "g1")])
(symbol=? s1 s2)) ;=> #f</pre>
<pre>(let ([s1 (generate-symbol "g1")] [s2 'g1])
(symbol=? s1 s2)) ;=> #f</pre>
<pre>(let ([s (generate-symbol "g1")])
(string=? (symbol->string s) "g1")) ;=> #f</pre>
<pre>(let ([s (generate-symbol)])
(symbol=? (string->symbol (symbol->string s)) s)) ;=> #t</pre>
<h2 id="implementation">Implementation</h2>
<p>A native implementation does not need to create a name for the
symbol returned by an application of <code>generate-symbol</code>
immediately but only lazily when <code>symbol->string</code> is
applied to the symbol for the first
time. If <code>symbol->string</code> is never applied as will likely
be the case in many uses of generated symbols, no name has to be
created. Symbols generated by <code>generate-symbol</code> can
therefore replace uninterned symbols known from some Scheme
implementations.</p>
<p>When an implementation has to create a name, it can simply choose a
randomly generated name so that the entropy of the random variable
described by <code>(lambda () (symbol->string (generate-symbol)))</code> is
sufficiently high (e.g. 122 bits as in the case of Version 4 UUIDs but
note that this SRFI prescribes no particular form of the symbol name).</p>
<p>The portable <a href="srfi/:260/generate-symbol.sls">sample
implementation</a> creates random names eagerly and
uses <code>/dev/random</code> for this purpose.</p>
<h2 id="acknowledgements">Acknowledgements</h2>
<p>This SRFI was created in response to <a href="https://srfi.schemers.org/srfi-258/srfi-258.html">SRFI 258: Uninterned Symbols</a>.</p>
<h2 id="copyright">Copyright</h2>
<p>© 2025 Marc Nieper-Wißkirchen.</p>
<p>
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:</p>
<p>
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.</p>
<p>
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.</p>
<hr>
<address>Editor: <a href="mailto:srfi-editors+at+srfi+dot+schemers+dot+org">Arthur A. Gleckler</a></address></body></html>