Skip to content

Commit 693d7ea

Browse files
committed
Clarify the different conventions between Scheme and Common Lisp
1 parent 881e0bc commit 693d7ea

File tree

1 file changed

+97
-17
lines changed

1 file changed

+97
-17
lines changed

CONTRIBUTING.md

Lines changed: 97 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -98,21 +98,35 @@ detail.](https://en.wikipedia.org/wiki/Scope_(computer_science)#Dynamic_scoping)
9898

9999
### Type system
100100

101+
Portable Scheme only has the predicates, such as `list?`. Scheme can
102+
be thought of as being "predicatively" typed. Airship Scheme uses this
103+
convention in its type names, making its Scheme type names end in `?`.
104+
101105
Technically, Common Lisp isn't just a "Lisp-2". It actually has more
102106
than two namespaces. The third most popular namespace is the *type*
103107
namespace, used by types defined by `defclass`, `deftype`, etc. One
104108
possible solution is to introduce this type namespace to Scheme, but
105-
standard Scheme is primarily typed by predicates. These could be seen
106-
as `satisfies` types in CL, but those are inefficient. The simplest
109+
standard Scheme is predicately typed. These could be seen as
110+
`satisfies` types in CL, but those are inefficient. The simplest
107111
efficient solution, then, is to have a `define-scheme-type` macro that
108112
defines both a type and a predicate of the same name (e.g. `pair?`).
109-
Normally, the generated predicate can just call `typep`, but there are
110-
quite a few special cases.
111113

112-
Technically speaking, this type namespace still exists and could be
113-
accessed through an exposed `type?` predicate in Scheme. For example,
114-
`(type? foo 'pair?)` would be `#t` if `foo` is a `pair?` even if
115-
`pair?` has been locally rebound in a `let`.
114+
Thus, in Airship Scheme, properly defined Scheme types always define a
115+
corresponding predicate of the same name, but are probably defined in
116+
a more efficient way (such as `define-scheme-type` on the CL side or
117+
`define-type` on the Scheme side).
118+
119+
This is generally done by automatically generating a trivially inline
120+
procedure that calls `typep` (in the CL side) or `type?` (in the
121+
Airship Scheme side). This means that this abstraction is a
122+
potentially leaky abstraction since the procedure might be redefined
123+
locally. However, `type?` will usually behave as expected because
124+
there is no local way to define a type.
125+
126+
That is, technically speaking, this type namespace still exists and is
127+
accessed through an exposed `type?` predicate on the Scheme side. For
128+
example, `(type? foo 'pair?)` would be `#t` if `foo` is a `pair?` even
129+
if `pair?` has been locally rebound in a `let`.
116130

117131
### Continuations
118132

@@ -157,6 +171,14 @@ procedure.
157171
Differing conventions
158172
---------------------
159173

174+
In general, Common Lisp has more consistent conventions than Scheme,
175+
with a few notable exceptions, such as Scheme's `!` naming convention
176+
for procedures with side effects. Where a clear convention exists in
177+
Scheme, Airship Scheme will follow that Scheme convention. Otherwise,
178+
Airship Scheme will borrow the convention from Common Lisp to ease
179+
interoperability, even if this convention hasn't been seen in Scheme
180+
before.
181+
160182
### Comments
161183

162184
In Common Lisp, end-of-line comments start with `;`. Comments on their
@@ -196,6 +218,15 @@ the three different levels of `;`s:
196218

197219
### Naming conventions
198220

221+
In Common Lisp, a slight variation of `foo` is usually called `foo*`.
222+
Something that's for low-level or internal-use is often called `%foo`.
223+
Airship Scheme uses this same convention.
224+
225+
Scheme uses `foo->bar` for conversion procedures while Common Lisp
226+
tends to use `foo-to-bar`.
227+
228+
#### Predicates
229+
199230
In Common Lisp, predicates end with `p`. The old convention is to end
200231
with `p` if it is one word, such as `foop`, and end with `-p` if it is
201232
more than one word, such as `foo-bar-p`. A newer convention is to
@@ -207,25 +238,41 @@ sense to make something look like it is a Common Lisp built-in, in
207238
particular when writing Common Lisp functions for
208239
`standard-procedures.lisp` to wrap.
209240

210-
Scheme procedures with side effects end in `!`, e.g. `foo!`, making it
211-
easy to tell when something is pure or not. In Common Lisp, there is
212-
no direct equivalent, but `nfoo` (where `n` stands for "nonconsing")
213-
and `foof` (in the style of `setf` or `incf`) are often used. Both are
214-
problematic because a function with side effects *can* still be
215-
"consing" (i.e. heap-allocating) and `foof` is specifically for
216-
dealing with "places". For that reason, Common Lisp code that must
241+
#### Side effects
242+
243+
Most Scheme procedures with side effects end in `!`, e.g. `foo!`,
244+
making it easy to tell when something is pure or not. In Common Lisp,
245+
there is no direct equivalent, but `nfoo` (where `n` stands for
246+
"nonconsing") and `foof` (in the style of `setf` or `incf`) are often
247+
used. Both are problematic because a function with side effects *can*
248+
still be "consing" (i.e. heap-allocating) and `foof` is specifically
249+
for dealing with "places". For that reason, Common Lisp code that must
217250
distinguish side effects in a clear way should use `!`, but that's not
218251
as necessary in Common Lisp as in Scheme. In this project, `!` should
219252
be used.
220253

221-
Scheme uses `foo->bar` for conversion procedures while Common Lisp
222-
tends to use `foo-to-bar`.
254+
Some built-in Scheme procedures with side effects do not end in `!`,
255+
such as `display`. This is for historical reasons. New Scheme
256+
procedures with side effects should end in `!`, but I/O procedures in
257+
the style of `display` might still seem more idiomatic to exclude it.
258+
259+
#### Global constants and variables
260+
261+
Common Lisp constants are surrounded in `+`s, like `+foo+`. Scheme
262+
does not have a consistent convention for constants, but some Scheme
263+
readers might not recognize tokens beginning with `+` that aren't the
264+
symbol `+` itself (used for addition) as a symbol because `+` is also
265+
a numeric prefix (e.g. `+42` is a number). Airship Scheme does not
266+
have this limitation, and so will use the Common Lisp `+foo+` naming
267+
convention for its constants.
223268

224269
Common Lisp global variables use "earmuffs", like `*foo*`. However,
225270
this is actually just a side effect of all portable Common Lisp global
226271
variables being dynamic (special) variables. Portable Scheme does not
227272
have dynamically scoped variables.
228273

274+
#### Definitions
275+
229276
In Common Lisp, `deffoo` is usually used for single word defines
230277
instead of `define-foo`, while `define-foo-bar` is always used for
231278
hyphenated names. This is not always the case. The Common Lisp
@@ -242,6 +289,39 @@ Lisp code really could use a tool that automatically distinguishes
242289
between predicates and non-predicates due to how the wrapping process
243290
works, but Airship Scheme is a rare, special case in its needs.)
244291

292+
#### Type names
293+
294+
Common Lisp types are generally written like everything else, in lower
295+
case, and often have name collisions (e.g. `list` the type and `list`
296+
the function that creates a list) that aren't an issue because the
297+
type namespace is a separate namespace (similar to how variables and
298+
functions have different namespaces). Scheme types are inconsistent,
299+
but many implementations capitalize the start of a type name, e.g.
300+
`List`.
301+
302+
As mentioned earlier, Airship Scheme uses the predicate convention in
303+
its type names, so all of its Scheme types should end in `?`. This is
304+
enforced through `define-scheme-type` on the CL side or `define-type`
305+
on the Scheme side.
306+
307+
There are some built-in ways to define types in ways that might
308+
violate this, but it is still maintained by convention to have the
309+
type and the predicate to test for the type have the same name. In
310+
Airship Scheme it is conventional to use the same name for the `name`
311+
and the `predicate` parts of `define-record-type`, although they can
312+
be different.
313+
314+
Scheme rarely provides efficient versions of various types, preferring
315+
the plainer definition, even if it requires a runtime predicate test.
316+
`exact-integer?` instead of `integer?` is a good example of where
317+
Scheme provides an efficient way, since `exact-integer?` will test for
318+
the underlying integer type (e.g. `42`) while `integer?` will test for
319+
the mathematical concept (including `42.0`).
320+
321+
When efficient versions don't exist, Airship Scheme will have to
322+
define them, such as `%list?`, which permits improper lists and should
323+
be preferred when working with lists.
324+
245325
*Cliki (the Common Lisp wiki) mentions the [Common Lisp naming
246326
conventions](https://www.cliki.net/Naming+conventions) in general and
247327
covers a lot of the same ground, with an emphasis on Common Lisp

0 commit comments

Comments
 (0)