Lisp
1. Common Lisp  cl common lisp
properties
ID: af0ed8bb-4b45-42f9-b8be-82b8ea7935a3
CREATED:
AKA: CL
edges
– Common Lisp
– common-lisp-libraries
– CL ANSI Standard Draft
– CLHS Starting Points
– quotes
– CDR - Common Lisp Document Repository
<- SBCL
<- ECL
The most powerful dialect of the most expressive language.
'Common' Lisp (CL) refers to any implementation of the ANSI CL Standard which fully describes the language.
CL began appearing in the Lisp world around 1984 and the spec itself was finalized in 1994. For the most part, the spec is a good enough baseline for a complete, high-level general-purpose language - which says a lot for a 30+ yr old description of a language without a reference implementation (that I know of).
Today () the best implementation of ANSI CL available is SBCL.
- Haskeller's perspective on Lisp: Lambda calculus - Lisp
1.1. Basic Syntax
properties
ID: df41336d-5185-4047-9644-e25925529f08
CREATED:
- Pragmatic Parsing in Common Lisp - ACM Lisp Pointers 4, 2 (Apr/Jun 1991), 3-15.
-
The common misconception is that Common Lisp is case insensitive. This is not true - symbols in Common Lisp are case sensitive.
By default, the Common Lisp reader is case-converting: all unescaped characters in a symbol name get upper-cased. This gives the practical effect of making it seem as though symbol case doesn't matter. This is desirable behavior for interfacing with other case-insensitive languages (such as Fortran), but a pain to interface with case-sensitive ones (such as C).
Luckily the behavior of the reader can be customized via readtable-case.
The one that might seem to be most useful for having case-sensitive symbols at first glance is :preserve, however remember that all code read in with the default setting (:upcase) is in upper-case, as are all the standard Common Lisp symbols (this is defined by the standard), so this means you will need to spell out all CL and external symbols IN ALL UPPERCASE. To make this less annoying, the :invert readtable-case is the most practical: all-lowercase symbol names become uppercase, all-uppercase become lowercase, and mixed-case stays mixed-case (the important part for case sensitivity). The Lisp printer outputs symbol names correctly this way by default. The only problem now becomes inconsistent spelling of a symbol in all lowercase or all uppercase in old code that expects case conversion. But otherwise you can get case sensitivity for your software by setting readtable-case to :invert today.
1.1.1. S-Expressions
properties
ID: 4e502dc1-c22d-444e-b4c0-864876f0cdf5
CREATED:
1.1.2. common-lisp unicode support
properties
ID: db68087d-cc4c-462d-b4e0-bbda756dc37c
CREATED:
logbook
- State "NOTE" from
(defmacro λ (&rest symbols-and-expr)
`(lambda ,(butlast symbols-and-expr)
,@(last symbols-and-expr)))
(mapcar (λ x (* x x)) '(1 2 3 4))
;; other tremendously useful characters:
'|αβγδεζηθικλμνξοπρστυϕχψω|
'|ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥϕΧΨΩ|
'|ℝℕℤℚ∥√∡∞∝ℵ∅∫|
'|¬∀∃∨∧⊥∈⊂∪∩⇐⇔⇒↦|
1.2. CLOS
properties
ID: 8bc4ff14-f001-4515-ac1f-fd59ef8ef506
CREATED:
1.2.1. Method Combination
properties
ID: 4e7b8135-3d53-4739-9a72-563971a5b876
CREATED:
edges
– 28.1.7.2. Standard Method Combination
– 28.1.7.3. Declarative Method Combination
– 28.1.7.4. Built-in Method Combination Types
– CLHS Macro DEFINE-METHOD-COMBINATION
- simple built-in method combination types
The names of the built-in method combination types are +, and, append, list, max, min, nconc, or, progn, and standard.
(define-method-combination xor :identity-with-one-argument t)
1.2.2. MOP
properties
ID: f9d8eead-51ab-4589-a5c2-2569ea1b7abd
CREATED:
AKA: Meta-Object Protocol
- fixed-indices allegro
- What sort of type checking is performed on slot-access, when that slot has type information? Does this vary at different compile levels?
- What is the performance impact of injecting additional slot-accessor type information? For example, declare as function-type with a typed result.
- https://www.reddit.com/r/lisp/comments/n88x59/metaclasses_using_structures_or_speeding_up_slot/
1.3. Types
properties
ID: 3f613b5a-6aae-4852-a4d8-c322c271e6eb
CREATED:
'(arithmetic-error function simple-condition array generic-function
simple-error atom hash-table simple-string base-char integer
simple-type-error base-string keyword simple-vector bignum list
simple-warning bit logical-pathname single-float bit-vector long-float
standard-char broadcast-stream method standard-class built-in-class
method-combination standard-generic-function cell-error nil
standard-method character null standard-object class number
storage-condition compiled-function package stream complex
package-error stream-error concatenated-stream parse-error string
condition pathname string-stream cons print-not-readable
structure-class control-error program-error structure-object
division-by-zero random-state style-warning double-float ratio symbol
echo-stream rational synonym-stream end-of-file reader-error t error
readtable two-way-stream extended-char real type-error file-error
restart unbound-slot file-stream sequence unbound-variable fixnum
serious-condition undefined-function float short-float unsigned-byte
floating-point-inexact signed-byte vector
floating-point-invalid-operation simple-array warning
floating-point-overflow simple-base-string floating-point-underflow
simple-bit-vector)
| ARITHMETIC-ERROR |
| FUNCTION |
| SIMPLE-CONDITION |
| ARRAY |
| GENERIC-FUNCTION |
| SIMPLE-ERROR |
| ATOM |
| HASH-TABLE |
| SIMPLE-STRING |
| BASE-CHAR |
| INTEGER |
| SIMPLE-TYPE-ERROR |
| BASE-STRING |
| KEYWORD |
| SIMPLE-VECTOR |
| BIGNUM |
| LIST |
| SIMPLE-WARNING |
| BIT |
| LOGICAL-PATHNAME |
| SINGLE-FLOAT |
| BIT-VECTOR |
| LONG-FLOAT |
| STANDARD-CHAR |
| BROADCAST-STREAM |
| METHOD |
| STANDARD-CLASS |
| BUILT-IN-CLASS |
| METHOD-COMBINATION |
| STANDARD-GENERIC-FUNCTION |
| CELL-ERROR |
| NIL |
| STANDARD-METHOD |
| CHARACTER |
| NULL |
| STANDARD-OBJECT |
| CLASS |
| NUMBER |
| STORAGE-CONDITION |
| COMPILED-FUNCTION |
| PACKAGE |
| STREAM |
| COMPLEX |
| PACKAGE-ERROR |
| STREAM-ERROR |
| CONCATENATED-STREAM |
| PARSE-ERROR |
| STRING |
| CONDITION |
| PATHNAME |
| STRING-STREAM |
| CONS |
| PRINT-NOT-READABLE |
| STRUCTURE-CLASS |
| CONTROL-ERROR |
| PROGRAM-ERROR |
| STRUCTURE-OBJECT |
| DIVISION-BY-ZERO |
| RANDOM-STATE |
| STYLE-WARNING |
| DOUBLE-FLOAT |
| RATIO |
| SYMBOL |
| ECHO-STREAM |
| RATIONAL |
| SYNONYM-STREAM |
| END-OF-FILE |
| READER-ERROR |
| T |
| ERROR |
| READTABLE |
| TWO-WAY-STREAM |
| EXTENDED-CHAR |
| REAL |
| TYPE-ERROR |
| FILE-ERROR |
| RESTART |
| UNBOUND-SLOT |
| FILE-STREAM |
| SEQUENCE |
| UNBOUND-VARIABLE |
| FIXNUM |
| SERIOUS-CONDITION |
| UNDEFINED-FUNCTION |
| FLOAT |
| SHORT-FLOAT |
| UNSIGNED-BYTE |
| FLOATING-POINT-INEXACT |
| SIGNED-BYTE |
| VECTOR |
| FLOATING-POINT-INVALID-OPERATION |
| SIMPLE-ARRAY |
| WARNING |
| FLOATING-POINT-OVERFLOW |
| SIMPLE-BASE-STRING |
| FLOATING-POINT-UNDERFLOW |
| SIMPLE-BIT-VECTOR |
1.3.1. Pathnames
properties
ID: 6935daca-1ad0-45b0-97e5-f59745f06ad9
CREATED:
;;; FIXME: the below shouldn't really be here, but in documentation
;;; (chapter 19 makes a lot of requirements for documenting
;;; implementation-dependent decisions), but anyway it's probably not
;;; what we currently do.
;;;
;;; Unix namestrings have the following format:
;;;
;;; namestring := [ directory ] [ file [ type [ version ]]]
;;; directory := [ "/" ] { file "/" }*
;;; file := [^/]*
;;; type := "." [^/.]*
;;; version := "." ([0-9]+ | "*")
;;;
;;; Note: this grammar is ambiguous. The string foo.bar.5 can be
;;; parsed as either just the file specified or as specifying the
;;; file, type, and version. Therefore, we use the following rules
;;; when confronted with an ambiguous file.type.version string:
;;;
;;; - If the first character is a dot, it's part of the file. It is not
;;; considered a dot in the following rules.
;;;
;;; - Otherwise, the last dot separates the file and the type.
;;;
;;; Wildcard characters:
;;;
;;; If the directory, file, type components contain any of the
;;; following characters, it is considered part of a wildcard pattern
;;; and has the following meaning.
;;;
;;; ? - matches any one character
;;; * - matches any zero or more characters.
;;; [abc] - matches any of a, b, or c.
;;; {str1,str2,...,strn} - matches any of str1, str2, ..., or strn.
;;; (FIXME: no it doesn't)
;;;
;;; Any of these special characters can be preceded by an escape
;;; character to cause it to be treated as a regular character.
- Logical Pathnames
properties
ID: bbdc87f1-cece-474f-905e-d02401e82510
CREATED:edges
– Zach Beane Common Lisp – Logical pathnames and eager parsing
– CLHS: System Class LOGICAL-PATHNAMEA pathname that uses a namestring syntax that is implementation-independent, and that has component values that are implementation-independent. Logical pathnames do not refer directly to filenames.
;;; Logical pathnames have the following format: ;;; ;;; logical-namestring ::= ;;; [host ":"] [";"] {directory ";"}* [name] ["." type ["." version]] ;;; ;;; host ::= word ;;; directory ::= word | wildcard-word | ** ;;; name ::= word | wildcard-word ;;; type ::= word | wildcard-word ;;; version ::= pos-int | newest | NEWEST | * ;;; word ::= {uppercase-letter | digit | -}+ ;;; wildcard-word ::= [word] '* {word '*}* [word] ;;; pos-int ::= integer > 0 ;;; ;;; Physical pathnames include all these slots and a device slot.
1.3.2. Simple Types
properties
ID: 62417b14-efff-448d-92c0-5b0e99a180ee
CREATED:
'(simple-array
simple-base-string
simple-bit-vector
simple-string
simple-type-error
simple-vector
simple-condition
simple-error
simple-warning)
| SIMPLE-ARRAY |
| SIMPLE-BASE-STRING |
| SIMPLE-BIT-VECTOR |
| SIMPLE-STRING |
| SIMPLE-TYPE-ERROR |
| SIMPLE-VECTOR |
| SIMPLE-CONDITION |
| SIMPLE-ERROR |
| SIMPLE-WARNING |
1.4. Conditions
properties
ID: 1535ca58-7141-4886-a1c0-90e4f29fc2c9
CREATED:
edges
– CLHS: Chapter 9
– Common Lisp: condition system
– Conditions (ANSI Common Lisp)
– Common Lisp: A Tutorial on Conditions and Restarts
– Conditions and Restarts in Common Lisp – Talking with a Lisp
– 29. Conditions
– CLHS: Chapter 9
- - the CL condition still baffles me - it is deeply expressive but I find it difficult to use. This might just be because there's nothing nearly as capable in other langs I've used.
serious-conditionimplies the need for user input, signaled witherrorinstead ofsignalorwarn.- CLHS style recommendations CLHS: Section 9.1.3.1
- uppercase first letter, use complete sentences and correct punctuation.
- don't prefix the message with things like 'Error: ' or even a newline. That's the job of the condition reporter
- it is permissible to embed newlines in messages (just not before or after)
- Avoid use of the #\Tab character
- Don't mention the containing function. That's the job of the debugger
1.5. Reader
properties
ID: d185b690-d2f8-46b9-a32d-2a95f0ee6d82
CREATED:
quick tip for reader macros - don't forget importance of the
.syntactic sugar'(foo . #.(list 1 2 3))FOO 1 2 3 (let ((a (list 1 2 3))) (equalp `(0 . ,a) ;; OR `(0 ,@a)))T
1.6. Printer
properties
ID: 0cdc5eb0-a12a-4276-8382-0b81f661a2a8
CREATED:
1.6.1. Pretty Printer
properties
ID: 681706ba-d885-46bf-93ba-c8e051c79aeb
CREATED:
Permits programs to redefine the way in which code is displayed and allow pretty printing to be applied to complex data structures.
The 'prettiness' of any particular output is somewhat subjective but in general the pretty printer allows individual programs to achieve an arbitrary degree of aesthetic control.
The pretty printer is driven entirely by dispatch based on the value
of *PRINT-PPRINT-DISPATCH* which is modified using
SET-PPRINT-DISPATCH.
Dynamic Control of the Arrangement of Output
The actions of the pretty printer when a piece of output is too large to fit in the space available can be precisely controlled. Three concepts underlie the way these operations work—logical blocks, conditional newlines, and sections.
Whenever possible, the pretty printer displays the entire contents of a section on a single line. However, if the section is too long to fit in the space available, line breaks are inserted at conditional newline positions within the section.
- tip: make sure to use the variables in code - for example the
*PRINT-PRETTY*var can be used to indicate color output is allowed inPRINT-OBJECTmethods.
A primary goal of pretty printing is to keep the output between a pair of margins. The column where the output begins is taken as the left margin. If the current column cannot be determined at the time output begins, the left margin is assumed to be zero. The right margin is controlled by print-right-margin.
1.7. Debugging
properties
ID: 4d5f7613-0441-4f69-b559-24f12ae39e15
CREATED:
1.8. Format Directives
properties
ID: 852b2c7f-238e-480d-ad63-3b5b53c58929
CREATED:
(let ((list-fmt "~@{~a ~^~}"))
(format nil list-fmt) ;; ""
(format nil list-fmt 1 2 3))
1 2 3
- Note that the extension mechanism (
~/foo/) is clunky - the character/isn't allowed in the function designator. - The core includes an annotation system (WIP )
- annotations are similar to format directives, just with a
different prefix character - usually
%(emacs style). - annotations are expanded as early as possible into a FORMAT control-string
- annotations are similar to format directives, just with a
different prefix character - usually
1.9. Functions
properties
ID: ebbc665a-10c3-46a3-8052-4f46bc9ac2b1
CREATED:
1.9.1. Lambda Expressions
properties
ID: 7555f8c6-5dd5-4607-ae1f-32643bf03ba9
CREATED:
This is not SBCL specific, but according to the ANSI Common Lisp standard.
Convert a Lambda Expression as List to a Function
These are your options:
CL-USER 168 > (funcall (coerce '(lambda (x) (* x x)) 'function) 4) 16
CL-USER 169 > (funcall (compile nil '(lambda (x) (* x x))) 4) 16
CL-USER 170 > (funcall (eval '(lambda (x) (* x x))) 4) ; because LAMBDA is a macro, too 16 CL-USER 171 > (funcall (eval '(function (lambda (x) (* x x)))) 4) 16
Note though that the lambda expression is referencing the null lexical environment. Thus it has no access to any lexical variables from the surrounding code.
Lambda expressions are not function objects
Why is a lambda expression not a function?
Because it is just a list, not code. To make a lambda expression into code, you have to turn it into a function object.
Some other (often older) Lisps allow you to use lambda expressions as code, but not Common Lisp. This is defined by the standard.
You can't do (funcall '(lambda (x) (+ x x)) 3). You have to convert the lambda expression into a function object first.
FUNCTION is a special operator -> syntax+semantics
(funcall (function (struct-slot1 struct1)) 3)
This is a syntax error, already. FUNCTION is a special operator and expects a function name or a lambda expression. (struct-slot1 struct1) is neither. (struct-slot1 struct1) is code which retrieves a value from a structure. But it is not a function name, which would be a symbol or a list (setf <some-symbol>). It is also not a lambda expression, which would be something like (lambda (…) . ..).
1.9.2. Thunk
properties
ID: d69c0095-59e3-4005-8360-f928c3ace460
CREATED:
- from tagbody in Lisp discord
the inventors of the thunk recalling that the term "was coined after they realized (in the wee hours after hours of discussion) that the type of an argument in Algol-60 could be figured out in advance with a little compile-time thought […] In other words, it had 'already been thought of'; thus it was christened a thunk, which is 'the past tense of "think" at two in the morning'.
1.10. Loop
properties
ID: 439a02f1-afcf-4ba3-bdf4-0304d152ba6f
CREATED:
Most of the so-called iteration control clauses start with the loop keyword for, or its synonym as,2 followed by the name of a variable. What follows after the variable name depends on the type of for clause.
The subclauses of a for clause can iterate over the following:
,* Ranges of numbers, up or down, by specified intervals ,* The individual items of a list ,* The cons cells that make up a list ,* The elements of a vector, including subtypes such as strings and bit vectors ,* The pairs of a hash table ,* The symbols in a package ,* The results of repeatedly evaluating a given form
A single loop can have multiple for clauses with each clause naming its own variable. When a loop has multiple for clauses, the loop terminates as soon as any for clause reaches its end condition. For instance, the following loop:
(loop for item in list for i from 1 to 10 do (something))
will iterate at most ten times but may stop sooner if list contains fewer than ten items.
The Parts of a LOOP
You can do the following in a LOOP:
,* Step variables numerically and over various data structures ,* Collect, count, sum, minimize, and maximize values seen while looping ,* Execute arbitrary Lisp expressions ,* Decide when to terminate the loop ,* Conditionally do any of these
Additionally, LOOP provides syntax for the following:
,* Creating local variables for use within the loop ,* Specifying arbitrary Lisp expressions to run before and after the loop proper
The basic structure of a LOOP is a set of clauses, each of which begins with a loop keyword.1 How each clause is parsed by the LOOP macro depends on the keyword. Some of the main keywords, which you saw in Chapter 7, are for, collecting, summing, counting, do, and finally.
Iterating over a hash table or package is slightly more complicated because hash tables and packages have different sets of values you might want to iterate over–the keys or values in a hash table and the different kinds of symbols in a package. Both kinds of iteration follow the same pattern. The basic pattern looks like this:
(loop for var being the things in hash-or-package …)
For hash tables, the possible values for things are hash-keys and hash-values, which cause var to be bound to successive values of either the keys or the values of the hash table. The hash-or-package form is evaluated once to produce a value, which must be a hash table.
To iterate over a package, things can be symbols, present-symbols, and external-symbols, which cause var to be bound to each of the symbols accessible in a package, each of the symbols present in a package (in other words, interned or imported into that package), or each of the symbols that have been exported from the package. The hash-or-package form is evaluated to produce the name of a package, which is looked up as if by FIND-PACKAGE or a package object. Synonyms are also available for parts of the for clause. In place of the, you can use each; you can use of instead of in; and you can write the things in the singular (for example, hash-key or symbol).
Finally, since you'll often want both the keys and the values when iterating over a hash table, the hash table clauses support a using subclause at the end of the hash table clause.
(loop for k being the hash-keys in h using (hash-value v) …) (loop for v being the hash-values in h using (hash-key k) …)
Both of these loops will bind k to each key in the hash table and v to the corresponding value. Note that the first element of the using subclause must be in the singular form.4
If none of the other for clauses supports exactly the form of variable stepping you need, you can take complete control over stepping with an equals-then clause. This clause is similar to the binding clauses in a DO loop but cast in a more Algolish syntax. The template is as follows:
(loop for var = initial-value-form [ then step-form ] …)
As usual, var is the name of the variable to be stepped. Its initial value is obtained by evaluating initial-value-form once before the first iteration. In each subsequent iteration, step-form is evaluated, and its value becomes the new value of var. With no then part to the clause, the initial-value-form is reevaluated on each iteration to provide the new value. Note that this is different from a DO binding clause with no step form.
The step-form can refer to other loop variables, including variables created by other for clauses later in the loop. For instance:
(loop repeat 5 for x = 0 then y for y = 1 then (+ x y) collect y) ==> (1 2 4 8 16)
However, note that each for clause is evaluated separately in the order it appears. So in the previous loop, on the second iteration x is set to the value of y before y changes (in other words, 1). But y is then set to the sum of its old value (still 1) and the new value of x. If the order of the for clauses is reversed, the results change.
(loop repeat 5 for y = 1 then (+ x y) for x = 0 then y collect y) ==> (1 1 2 4 8)
Often, however, you'll want the step forms for multiple variables to be evaluated before any of the variables is given its new value (similar to how DO steps its variables). In that case, you can join multiple for clauses by replacing all but the first for with and. You saw this formulation already in the LOOP version of the Fibonacci computation in Chapter 7. Here's another variant, based on the two previous examples:
(loop repeat 5 for x = 0 then y and y = 1 then (+ x y) collect y) ==> (1 1 2 3 5)
- The possible verbs are collect, append, nconc, count, sum, maximize, and minimize. Also available as synonyms are the present participle forms: collecting, appending, nconcing, counting, summing, maximizing, and minimizing.
- As an extra bit of syntactic sugar, within the first loop clause,
after the test form, you can use the variable it to refer to the
value returned by the test form. For instance, the following loop
collects the non-NIL values found in some-hash when looking up the
keys in some-list:
(loop for key in some-list when (gethash key some-hash) collect it)
1.11. Concurrency
properties
ID: d9062d16-09f0-4c48-99ac-2e26407fc75b
CREATED:
1.12. Macros
properties
ID: 1ccb1faa-6e41-4b4f-877f-4382bc250e53
CREATED:
1.12.1. Compiler Macros
properties
ID: 961d0c81-11f0-49e2-8ccb-9c31f6b6528d
CREATED:
1.13. Applications
properties
ID: 475491e1-eacd-4759-be06-1c027e91f565
CREATED:
1.13.1. screenshotbot-oss
properties
ID: 54d32d4a-93fe-4f4d-9207-f291dbb1edc6
CREATED:
A Screenshot Testing service to tie with your existing Android, iOS and Web screenshot tests.
1.13.2. Nyxt
properties
ID: c57d3869-02d6-4e5d-bb09-804d18c07124
CREATED:
1.13.4. StumpWM
properties
ID: abcd966f-fd1b-4679-b956-fc4891647668
CREATED:
1.14. Libraries
properties
ID: 82d4dffa-070c-4ead-b317-9f9b6820e2c1
CREATED:
1.14.1. CL-PPCRE
properties
ID: f666c1b5-2900-44a2-85ba-2afb029d32ab
CREATED:
CL-PPCRE is a portable regular expression library for Common Lisp which has the following features:
- It is compatible with Perl (especially when used in conjunction with cl-interpol, to allow compatible parsing of regexp strings).
- It is pretty fast.
- It is portable between ANSI-compliant Common Lisp implementations.
- It is thread-safe.
- In addition to specifying regular expressions as strings like in Perl you can also use S-expressions.
- It comes with a BSD-style license so you can basically do with it whatever you want.
1.14.2. one-more-re-nightmare
properties
ID: cc72c2c8-8a05-432e-8e7a-844eb6c9ac15
CREATED:
1.14.3. CLIM  gui
properties
ID: d68d93f2-dbeb-410c-8fee-af71d3a4b0a0
CREATED:
- McCLIM
properties
ID: b93f8626-0816-4de6-b6bd-9c796be468e8
CREATED:edges
– McCLIM - A powerful GUI toolkit for Common Lisp
– Guided Tour (2006)
– src
– McCLIM User's ManualMcCLIM is a FOSS implementation of the Common Lisp Interface Manager specification.
Frame Redefinition
By default when the application frame class is redefined with the macro clim:define-application-frame panes and layouts of the existing instances are not changed. To update the frame programmer must call the function reinitialize-instance. The function may be called on a running frame ouside of its event loop.
McCLIM extends the macro clim:define-application-frame to update existing frames automatically when the new option :reinitialize-frames is not nil. Instances are updated by defining a method update-instance-for-redefined-class :after and making all instances obsolete. Then a slot of each adopted frame is read to trigger the update without delay.
- When the option is nil (a default) then nothing happens.
- When the option is t then all instances are updated by calling on them the function reinitialize-instance (running frames are updated immedietely and the reset whenever the implementation chose to call the function update-instance-for-redefined-class).
- When the option is a plist then additionally this plist is prepended to initargs applied to the function reinitialize-instance.
1.14.4. CLX  gui
1.14.5. Shirakumo
properties
ID: 503387d8-fa9c-4269-99bc-1d29415ab290
CREATED:
Shinmera runs an indie-game studio based on CL and has contributed well over 10% of the Quicklisp ecosystem. Impressive effort and worthy of a dedicated info node here.
- Radiance  web
properties
ID: 1beb282b-8c4d-4561-a293-07439d0367ae
CREATED: - Alloy  gui
properties
ID: 8af234c8-1455-4dc8-a2df-e6d5b5777606
CREATED: - Framebuffers
properties
ID: e70d50df-d897-4a5f-a669-fa5dc3f94b23
CREATED:
1.14.6. Fukamachi
properties
ID: 0fa56fd5-0b93-4b2f-be00-8197275bb5ef
CREATED:
Tokyo-based Lisp hacker and web developer with some excellent CL packages.
- quri
properties
ID: df045d95-a55e-4e87-a450-cf683e0ebd19
CREATED: - clack  web
properties
ID: c9515816-fc3a-4976-a5ed-138cbec83aa9
CREATED:lack the core of clack
Lack is a Common Lisp library which allows web applications to be constructed of modular components. It was originally a part of Clack, however it's going to be rewritten as an individual project since Clack v2 with performance and simplicity in mind.
The scope is defining Lack applications and wrapping it up with Lack middlewares. On the other hand, Clack is an abstraction layer for HTTP and HTTP servers and provides unified API.
- woo  web
properties
ID: 98b691b5-a617-438e-80ec-fb31588bcc3e
CREATED: - sxql  sql
properties
ID: ac5922a8-06c6-4608-8305-ec42ceea4ee9
CREATED:
1.14.7. Coalton
properties
ID: 20ea4fcc-e435-4738-93f3-a29572f0919b
CREATED:
Coalton is an efficient, statically typed functional programming language that supercharges Common Lisp.
1.14.8. Gambol  prolog
properties
ID: a911344d-aed1-4603-a46f-e8edf53756f5
CREATED:
See also A Common Prolog
- in any case we basically always want to drop into a Read-Query-Print loop
- in Common Prolog this function is called
RQP
1.14.9. lparallel
properties
ID: c560dc07-8c9c-42bc-9ce1-634630d26981
CREATED:
- provides thread-pools in the form of kernels
- our implementation in the core is very similar but we use the 'thread-pool' terminology. We also provide a general purpose KERNEL slot for many types of objects including thread-pools and workers. For workers the kernel is called to start the worker loop and in thread-pools it is called with a single keyword argument to change the state of the thread-pool.
1.14.10. parenscript  js
properties
ID: c42732ce-9ef1-408b-a9dd-2424d05de398
CREATED:
Compiling Parenscript | jsloop
Parenscript is a subset of Common Lisp that compiles to JavaScript. The emphasis is on the fact that it strives to produce minimal JavaScript like 1:1 as much as possible. Unlike ClojureScript which produces a lot of dependent code because of the use of Google Closure library for everything.
1.14.11. jscl  js
properties
ID: 3addee17-b990-4a6d-9767-071969ed9d0e
CREATED:
edges
– jscl-project/jscl: A Lisp-to-JavaScript compiler bootstrapped from Common Lisp
-> Javascript
A CL to JS compiler
- supplies a light js runtime with a web worker
- lisp code compiled directly to js stream
- supports CL/JS ffi
1.14.12. Symbolics
properties
ID: b8d8538c-7be9-4271-bf8e-897e9ba5b6ad
CREATED:
- TODO find web source to link to
- /var/lib/symbolics/sys.sct
- demo/organ.lisp
- io/iterators.lisp
- io/rtc.lisp (fsm)
wisdom from clim/demo/thinkadot.lisp:
;;; in all node-state stuff, t = left, nil = right (defstruct td-node (direction t) left-successor right-successor x y (color-phase nil) (entry-p nil))
1.14.13. CL-GSERVER
properties
ID: 0aa28dd2-d424-4021-a775-095439dffd7a
CREATED:
AKA: Sento
edges
– [BROKEN LINK: github:mdbergmann/cl-gserver]
An actor framework
1.14.14. C-mera
properties
ID: 26cd6032-0e6e-4f9b-ae9f-2b88aa95dafc
CREATED:
edges
– [BROKEN LINK: github:kiselgra/c-mera]
C-Mera is a particularly powerful Lisp system - it's a source2source transpiler built entirely on Lisp Macros.
It can be a bit difficult to navigate the source, and in our case
mimick it in our own implementation - our fork is in SYN/GEN, and
utilizes AST nodes from OBJ/AST - it is not limited to just C
languages and so the design may be quite different in some places.
The first oddity in C-Mera's source comes in the system definition
c-mera.asd. All packages and symbol exports are set here with
several variables defined for lists of symbols.
- CL-SYMBOLS
- all external symbols in the COMMON-LISP package
- DEFAULT-EXPORTS
- default package exports
- C-MERA-BACKEND
- global ast + slot symbols
In the case of C we have the following symbols bound:
- C-BACKEND
- ast + slot symbols
- C-SYMBOLS
- list used for package definition with shadowed symbols and for the cm/lisp scope switch
- C-SYNTAX
- symbols not shadowed but exported
- C-EXPORTS
- the full list of exports - includes C-SYMBOLS, C-SYNTAX, DEFAULT-EXPORTS, and CL-SYMBOLS
- C-SWAP
- (append C-SYMBOLS C-SYNTAX)
Next the actual packages are defined with the help of a DEFPACKAGE*
macro. There are four variations - the core package (C-MERA), the
backend package (CM-C), the user package (CMU-C), and swap packages
(CMS-C). The core package never changes and is used by the backend
packages, but NOT by the user packages. In both cases the C variants
of the backend and user packages are imported into subsequent packages
defined and swap packages are defined as empty.
ALL PACKAGES then get their own systems defined with dependencies assigned like so: C-MERA - CM-C - CMU-C - CMS-C
(asdf:defsystem c-mera
:name "c-mera"
:version "1.1.0"
:serial t
:components ((:file "src/c-mera/version")
(:file "src/c-mera/cmd")
(:file "src/c-mera/nodes")
(:file "src/c-mera/utils")
(:file "src/c-mera/traverser")
(:file "src/c-mera/pretty")
(:file "src/c-mera/c-mera"))
:depends-on ("net.didierverna.clon.core"))
;; ...
(asdf:defsystem cm-c
:name "c-mera c"
:version "1.1.0"
:serial t
:components ((:file "src/c-mera/c-mera")
(:file "src/c/utils")
(:file "src/c/nodes")
(:file "src/c/traverser")
(:file "src/c/pretty")
(:file "src/c/syntax")
(:file "src/c/reader")
(:file "src/c/cm-c"))
:depends-on ("c-mera"))
;; ...
(asdf:defsystem cmu-c
:name "c-mera user c"
:version "1.1.0"
:components ((:file "src/c/cmu-c"))
:depends-on ("c-mera"
"cm-c"))
;; ...
(asdf:defsystem cms-c
:name "c-mera swap c"
:version "1.1.0"
:depends-on ("cmu-c"))
1.14.15. Swank
properties
ID: a69e0d55-e25f-4332-8fdc-aad2843ba649
CREATED:
The server and protocol components of SLIME. Included in the same repo.
See also swank-client which provides a client-side-only protocol implementation.
Swank is TCP-based and unencrypted by default.
1.14.16. Elephant
properties
CREATED:
ID: d0fc3dc0-3ff9-442c-9eb2-97661a4a4cbe
- similar goals to XDB, but not lisp-native (provides systems for BDB and CLSQL)
- our own STORE protocol is quite similar
notes
- tons of useful documentation in the doc/ subdir
one thing I haven't thought much about is how and when to initialize the 'stored index' containing an ordered collection of lisp values - figure out 'warm boot'.
The use of persistent objects makes coding concise, convenient, and powerful, and makes persistence almost invisible to the programmer. However, Elephant also allows the same basic data dictionary of key/value retrieval that BerkeleyDB provides.
(in our case RDB)
While Elephant can use either RDBMSs or Berkeley DB as a data store, the model it supports is that of objects stored in persistent indices. Unlike systems such as Hibernate for Java, the user does not need to construct or worry about a mapping from the object space into the database. Elephant relies on LISP rather than SQL for its data manipulation language. Elephant is designed to be a simple and convenient tool for the programmer.
Concepts:
- store controller (store)
- persistent sets (psets)
- Btrees - sorted order persistent KV abstraction
- stored values - most lisp values including standard objects/arrays, can be used as either key or value in a btree
- persistent objects - objects where most slot values are stored in the data store and IO performed on slot access. Storing a persistent object in a btree only store a reference for object identity.
- object indexing - the ability to lookup and sort objects by their slot values rather than by explicit inclusion in a collection.
- transactions - dx for executing operations on objects or collects (transaction/txn)
Basic operation is OPEN-STORE with a spec (cons where car is a backend kw), do stuff, then CLOSE-STORE. Alternatively WITH-OPEN-STORE.
What values live between lisp sessions is called liveness. Liveness in a store is determined by whether the value can be reached from the root of the store. The root is a special BTree in which other BTrees and lisp values can be stored. This BTree has a special interface through the store controller. (There is a second root BTree called the class root which will be discussed later.)
use ADD-TO-ROOT to put something into the root object and GET-FROM-ROOT to retrieve it. See also ROOT-EXISTSP, REMOVE-FROM-ROOT, MAP-ROOT. The root object itself can be accessed from the store itself.
important notes:
'This will affect all aggregate types: objects, conses, hash-tables, et cetera.'
- Lisp identity can't be preserved - if you get an object from the index, store as a lisp variable and then get it again, the two objects won't be EQ.
- Nested aggregates are stored in one buffer
- Mutated substructure does not persist
- Serialization and deserialization can be costly
- Merge-conflicts in heavily multi-process/threaded situations
- persistent classes
- serialized by their OID and class
- slot values are store separately (and invisible to the user), keyed by OID and slot
- loading (deserializing) a persistent class instantiates the object or finds it in a cache if it already exists.
- the cache is a weak hash-table.
- slot values are NOT loaded until you ask for them. persisted slots don't have space allocated for them because we read from the DB.
- Changes persist immediately
- serde of persistent classes is fast, much faster than ordinary clos objects.
- do not suffer from merge conflicts
- declares all slots be persistent by default - use
:transient tfor non-persistent. - class slots with
:allocation :classare never persisted
Persistent classes may inherit from other classes. Slots inherited from persistent classes remain persistent. Transient slots and slots inherited from ordinary classes remain transient. Ordinary classes cannot inherit from persistent classes – otherwise persistent slots could not be stored!
to simulate a new lisp session: FLUSH-INSTANCE-CACHE
Using persistent objects has implications for the performance of your system. Note that the database is read every time you access a slot. This is a feature, not a bug, especially in concurrent situations: you want the most recent commits by other threads, right? This can be used as a weak form of IPC. But also note that in particular, if your slot value is not an immediate value or persistent object, reading will cons or freshly allocate storage for the value.
Gets are not an expensive operation; you can perform thousands to tens of thousands of primitive reads per second. However, if you're concerned, cache large values in memory and avoid writing them back to disk as long as you can.
- persistent collections
- pset and btree are the solutions provided for the setf problem
Each provides persistent addition, deletion and mutation of elements, but the pset is a simple data structure that may be more efficient in memory and time than the more general btree.
The
psetis also a very convenient data structure for enabling a persistent slot contain a collection that can be updated without deserializing and/or reserializing a list, array or hash table on every access.The only difference is the api used to manipulate it. Instead of slot accessors, we use insert, remove, map and find.
There is one drawback to persistent sets and that is that they are not garbage collected. Over time, orphaned sets will eat up alot of disk space. Therefore you need to explicitly free the space or resort to more frequent uses of the migrate procedure to compact your database. The pset supports the drop-pset
However, given that persistent objects have the same explicit storage property, using psets to create collection slots is a nice match.
BTrees are collections of key-value pairs ordered by key with a log(N) random access time and a rich iteration mechanism. Like persistent sets, they solve all the collection problems of the prior sections. Every key-value pair is stored independently in Elephant just like persistent object slots.
The primary interface to btree objects is through get-value. You use setf get-value to store key-value pairs. This interface is very similar to gethash.
In addition to the hash-table like interface, btree stores pairs sorted by the lisp value of the key, lowest to highest. This is works well for numbers, strings, symbols and persistent objects, but due to serialization semantics may be strange for other values like arrays, lists, standard-objects, etc.
see MAP-BTREE
- indexing persistent classes
(defsclass foo () () (:index t))
Notice the class argument ``:index t''. This tells Elephant to store a reference to this class. Under the covers, there are a set of btrees that keep track of classes
GET-INSTANCES-BY-CLASS returns all created instances, or more efficiently for iteration MAP-CLASS
Elephant makes no guarantee about the ordering of class elements, so you cannot depend on the insertion ordering
If we want ordered elements.. use slot indices!
(defsclass foo () ((a :index t) (b :index t)))
get-instances-by-value will retrieve all instances that are equal to the value argument, with the equality relation defined by the database backend.
TODO: GET-INSTANCES-BY-RANGE
To map over duplicate values, use the :value keyword argument. To map by range, use the :start and :end arguments.
MAP-CLASS-INDEX
- Transactions
- use WITH-TRANSACTION macro
- no dynamic nesting and idempotent side-effects
- to perform a group of transactions, use ENSURE-TRANSACTION for each unit, which will reuse an existing transaction if there is one.
- the side effects of the body must be the same no matter how many times the body is executed
The best rule-of-thumb is to ensure that transaction bodies are purely functional as above, except for side effects to persistent objects and btrees.
If you really do need to execute side-effects into lisp memory, such as writes to transient slots, make sure they are idempotent and that other processes cannot read the written values until the transaction completes.
We cannot have infinitely sized transactions due to the finite size of the data store's memory cache. Large operations (such as loading data into a database) need to be split into a sequential set of smaller transactions. When dealing with persistent objects a good rule of thumb is to keep the number of objects touched in a transaction well under 1000.
on to the guide..
- all lisp objects are stored by value
- native byte ordering
Atomic Types
nilhas it's own special tag in the serializer so it is easily
identifiable. nil is an awkward value as it is also a boolean. The boolean value
tis stored as the symbol'T.- Bignums are broken into a sequence of fixnum-sized chunks and
assembled by masking words onto the bignum. This is awfully expensive, but it's always correct and fully portable.
- A rational is merely a ratio of two integers stored as fixnums or bignums.
- A complex is a pair of floating point values, rationals or integers.
- Standalone chars are represented by their char-code and are stored in 32-bit format to ensure that all lisps are stored correctly.
- Symbols are stored as two strings, the package name and the symbol name in that package. When deserialized, the target package is searched for and the symbol is interned in that package.
- Aggregate Types
- Cons is simply stored as a cons record containing two nested elements. Linear lists are not treated specially (i.e. no cdr-coding) by the serializer.
- Arrays are stored as sequences of nested, serialized elements. The array parameters are also stored so that arrays with fill pointers, adjustable arrays can be stored and reconstructed. The only arrays that cannot be reproduced are displaced arrays, which are copied by value and reconstructed as standard arrays during deserialization.
- Hash tables are stored as a sequence of key-value pairs, where the
key and value can be any serializable value. On deserialization,
the reconstructed key and value quantities are written
incrementally into the hash table. The hash table does remember
it's test, rehash size and threshold and it's total count. The
final size of the new hash table is set to
(* (/ size reshash-threshold) rehash-size). - Structure objects are serialized using the metaprotocol. Each
slot where the value is bound is serialized by serializing the
slot name and the value in sequence. The underlying lisp must
support the
struct-constructormethod so that a new, empty instance of the structure can be created and then populated by the stored keys and values. - Instances of subclasses of standard-object are stored almost identically to structs. The type of the object is stored and the object slots with bound values are serialized as slotname-value pairs. To read an object of this type, the lisp image must have the class defined and it must have at least the slots that are stored on disk. There is no good method for schema evolution (redefining objects to have less slots) of ordinary classes.
After initialization of a stored object the following state has been created:
- placeholder instance
- in memory, storage for oid, spec, lisp instance data and transient slot values. mediates access to stored values, does not persist itself.
- cached reference
- weak reference to instance in the store object cache
- memory references
- a normal reference to the instance may be retained by the caller
- database slot values
- the data store contains the stored slot values that were initialized, indexed by the object id and slot name
- database references
- if placeholder instance is written to a
stored slot, added to a btree, or the class is indexed, a
referenceto the instance was added to the data store. This reference consists of an OID and a class name. If this reference is reachable, then the stored object can be reconstructed using the:FROM-OIDkeyword argument.
If you manually create an object using an OID which already exists in
the database, initargs to make-instance take precedence over
existing values in the database, which in turn take precedence over
any initforms defined in the class.
- LIFETIMES
The distributed nature of persistent instance storage results in some interesting behaviors, especially with respect to transient slots. The prior section detailed the state of the system after the original initialization of an object. The object can then be in a number of different states:
- resident
- the canonical state of an in-use stored object
- unreferenced, unreclaimed
- all memory refs dropped but placeholder hasn't been reclaimed. Weak pointer still exists in object cache. If a database ref is fetched, the cached value will be used.
- Non-resident
- The object only exists as reachable database refs and slot values. This is the state after GC of the placeholder.
- Recreated
- An intermediary state where a non-resident object is
fetched from the data store and its placeholder must be recreated
prior to the object entering residency state.
when a ref is deserialized, its OID is used to lookup the object in the store object cache. If this fails the instance is created with a call such as:
(make-instance 'sclass :from-oid 2000 :store *store*):from-oidinhibits somemake-instancebehavior
A good policy is to initialize transient values using an :after
method on initialize-instance. This allows you to initialize transient
values using either system defaults or persistent slot values. That
way you can ensure that the transient slots are always in a consistent
state when accessed by the application, regardless of when the
placeholder object was recreated.
In general, transient slots are a good place for intermediate values in a computation or to cache frequently read items to avoid deserialization overhead. indexed-btree is an example of this approach, an in-memory hash is cached in the transient slot for reads and writes are mirrored to a serialized hash in a persistent slot. The :after method just copies the persistent hash value to the transient slot.
Creating a set-valued slot:
(defsclass my-set ()
((set-slot :accessor set-slot :initform nil :set-valued t)))
see SET-INSERT, SET-LIST
- Association Slots
Assocation slots allow you to create relationships between objects in your system. In the following set of examples two classes are created, a 'job' class and a 'person' class. These classes are related in that each person can only be associated with one job, but a job might have multiple people associated with it. To capture this relationship in Elephant you can use Association slots.
You can enable/disable class indexing for an entire class. When you disable indexing all references to instances of that class are lost. If you re-enable class indexing only newly created classes will be stored in the class index. You can manually restore them by using
find-class-indexto get the clas index BTree if you have an alternate in-memory index.You can add/remove a secondary index for a slot. So long as the class index remains, this can be done multiple times without losing any data.
There is also a facility for defining 'derived slots'. These can be non-slot parameters which are a function of the class's persistent slot values. For example you can use an index to keep an alternate representation available for fast indexing. If an object has an x,y coordinate, you could define a derived index for r,theta which stored references in polar coordinates. These would be ordered so you could iterate over a class-index to get objects in order of increasing radius from the origin or over a range of theta.
…
Thus, the question of if and how a given class should be indexed is very flexible and dynamic, and does not need to be determined at the beginning of your development. This represents the ability to ``late bind'' the decision of what to index.
In general, there is always a tradeoff: an indexed slot increases storage associated with that slot and slows down write operations. Reads however remain as fast as for unindexed persistent slots. The Elephant system makes it simple to choose where and when one wants to utilize this tradeoff.
- see also src/elephant/classindex-utils.lisp - documents tools for handling class redefs and polcies that should be used for synchronization.
*default-indexed-class-sync-policy*values:- :class - class is master, indices are deleted for any slots no longer indexed
- :db - db is master, class indexing annotations are updated so
slots which satisfy
class-indexedp-by-nameare isomorphic to the existing indices in the db. - :union - expected result - updates the class to match any existing indices and creates new ones.
- BTrees
- core data structure, Elephant directly exposes it
- basic API is:
get-value,remove-kv - Sorting is done first by primitive type (string, standard-class,
array, etc) and then by value within that type. The type order
and internal sorting constraint is:
- Numbers - effectively coerced to double float and sorted relatively
- strings - varwidth - width type sorted separately?? hmm
- pathnames,symbols - sorted by string radix then lexically
- aggregates sorted by type in following order then arbitrary: stored instance refs, cons, hash-table, standard objects, arrays, structs, then nil.
- not GC'd (like ssets) - use
drop-btreeto delete all KV pairs and return storage - the OID used will not be recovered.
- Btree Cursors
- used to traverse btrees one KV at a time
- must be created inside a transaction - made with call to
make-cursormethod of btree. Make sure to close cursor when stack is unwound, best to usewith-btree-cursor. - can duplicate cursors with
cursor-duplicate- avoids overhead - two states: initialized or uninitialized
- to initialize:
cursor-firstorcursor-lastcursor-setorcursor-set-range
- once initialized cursor can be incremented or decremented - O(1)
cursor-nextorcursor-prev
- can use cursors for side effects:
cursor-putreplace the value without incrementing andcursor-deletedeletes the KV pair and becomes uninitialized.
- BTree Indexing
indexed-btreemaintains a set ofbtree-indexinstances which provide alternative indexing algos.- Each index is itself a btree with values matched to the keys of the parent btree.
- Index is created with
add-index - important property of
btree-index: allows duplicate keys. No dupes allowed in btree and indexed-btree. - index cursors are just like btree cursors except you can get the
main btree value instead of the indexed valued. parallel set of
operations -
cursor-pnextfor example returns (exists, key, primary-btree-value, index-value = primary-btree-key).
The big difference between btree cursors and index cursors is that indices can have duplicate key values. This means we have to choose between incrementing over elements, unique key-values or only within a duplicate segment. There are cursor operations for each:
- Simple move - standard btree ops and cursor-pnext/cursor-pprev
- Move to different KV (cursor-pnext-nodup and cursor-pprev-nodup)
- Move to next duplicate KV (cursor-pnext-dup and cursor-pprev-dup)
- after incrementing through a set of dupes the last NEXT operation returns nil indicating no more dupes - consequence is the cursor is uninitialized and needs to be reset.
Shared Resource Locks:
- store connection table
- instance cache
- circularity buffer pool for serializer
- static-streams for FFI (rw: is this needed?)
You can trace
execute-transactionto see the sequence of calls that occur dynamically and detect where and how many transactions are and are not happening.
- Repository migration and upgrade
(see tests migrate1-5)
- single generic
migratefunction
- single generic
It is assumed that typically migrate will be called on two repositories and all live objects (those reachable in the root or class-root) will be copied to the target repository via recursive calls to migrate for specific objects.
Migrate will not handle:
- circular lists
- Indexed classes only have their class index copied if you use the top level migration.
- one-time activity - should close the source store after validation
- cannot currently migrate a store that has more data than your main memory. (rw: we can probably fix this)
- OID equivalence is not maintained - can overload the migrate method to accomplish this
To customize migration overload a version of migrate to specialize on your specific persistent class type.
(defmethod migrate ((dst store-controller) (src my-class)))In the body of this method you can call
(call-next-method)to get a destination repository object with all the slots copied over to the target repository which you can then overwrite. To avoid the default persistent slot copying, bind the dynamic variable*inhibit-slot-writes*in your user method usingwith-inhibited-slot-copya convenience macro.
- Performance is usually measured in transactions per second. Database reads are cheap.
All data written to the data store ends up in a BTree slot using a transaction. There are two databases, one for persistent slot values and one for btrees. The mapping of Elephant objects is quite simple.
Persistent slots are written to a btree using a unique key and the serialized value being written. The key is the oid of the persistent object concatenated to the serialized name of the slot being written. This ordering groups slots together on the disk
1.14.17. IOLib
properties
ID: 894ce499-1ce7-4051-a921-661995fe42b2
CREATED:
edges
– [BROKEN LINK: github:sionescu/iolib]
IOLib is a portable I/O library for ANSI Common Lisp. It includes socket interfaces for network programming with IPV4/IPV6 TCP and UDP, an I/O multiplexer that includes nonblocking I/O, a DNS resolver library, and a pathname library.
- depends on libfixposix
1.15. Systems
properties
ID: a6911466-c135-488c-a67e-689f22592a44
CREATED:
Systems are not part of the ANSI CL spec. They are classes defined by the ASDF package.
A system is a collection of Lisp files that together constitute an application or a library, and that should therefore be managed as a whole. A system definition describes which source files make up the system, what the dependencies among them are, and the order they should be compiled and loaded in.
- There are some other adhoc solutions out there but nothing that caught steam. If you want to work with the rest of the CL ecosystem you basically need to use ASDF.
1.15.1. ASDF
properties
ID: fb68413a-acd8-4107-bfb5-48ce32be8842
CREATED:
- makes use of (call-with-x thunk) -> (with-x ,@body) often
- with-upgradability wrappers all over the place for backwards-compatibility
- Sessions
properties
ID: 2a62e513-65a6-49f0-9965-d25710186bc3
CREATED:- asdf:session
- An ASDF session with a cache to memoize some computations
The ASDF session cache is used to memoize some computations. It is instrumental in achieving:
- Consistency in the view of the world relied on by ASDF within a given session. Inconsistencies in file stamps, system definitions, etc., could cause infinite loops (a.k.a. stack overflows) and other erratic behavior.
- Speed and reliability of ASDF, with fewer side-effects from access to the filesystem, and no expensive recomputations of transitive dependencies for input-files or output-files.
- Testability of ASDF with the ability to fake timestamps without actually touching files.
1.16. Packages
properties
ID: 92dd3f0e-4789-4016-a623-48af3c45cd05
CREATED:
- CLHS: Function SHADOW
- :intern
The symbols named by the argument symbol-names are found or created in the package being defined. The :intern option interacts with the :use option, since inherited symbols can be used rather than new ones created.
It is recommended that the entire package definition is put in a single place, and that all the package definitions of a program are in a single file. This file can be loaded before loading or compiling anything else that depends on those packages. Such a file can be read in the COMMON-LISP-USER package, avoiding any initial state issues.
- SBCL supports some additions to defpackage (:lock and :implement) -
uiop and our own
defpkgsupports even more (:recycle, etc) - SBCL Package Locks
:implement
Each package has a list of associated implementation packages. A locked package, and the symbols whose home package it is, can be modified without violating package locks only when
*package*is bound to one of the implementation packages of the locked package.Unless explicitly altered by defpackage,
sb-ext:add-implementation-package, orsb-ext:remove-implementation-packageeach package is its own (only) implementation package.- Package-local nicknames
1.17. Tools
properties
ID: 7f63f416-efcb-4926-8370-b626c4349c45
CREATED:
1.17.1. lisp-critic
properties
ID: d0796fff-4a90-42a5-8213-93e2cb5c9465
CREATED:
The Lisp Critic scans your code for instances of bad Lisp programming practice.
? (critique
(defun count-a (lst)
(setq n 0)
(dolist (x lst)
(if (equal x 'a)
(setq n (+ n 1))))
n))
----------------------------------------------------------------------
Don't use SETQ inside DOLIST to accumulate values for N.
Use DO. Make N a DO variable and don't use SETQ etc at all.
----------------------------------------------------------------------
You have an IF with no else branch. If the return value of the IF
matters, you should explicitly say what the else returns, e.g., NIL.
If the return value doesn't matter, use WHEN or UNLESS.
----------------------------------------------------------------------
INCF would be simpler to add 1 to N than SETQ
----------------------------------------------------------------------
GLOBALS!! Don't use global variables, i.e., N
----------------------------------------------------------------------
Unless something special is going on, use EQL, not EQUAL.
----------------------------------------------------------------------
Don't use (+ N 1), use (1+ N) for its value or (INCF N) to change N,
whichever is appropriate here.
----------------------------------------------------------------------
1.18. Blogs
properties
ID: f677579e-a644-444f-90e6-442909f94ef8
CREATED:
1.18.1. Structural Insight
properties
ID: a1002554-61eb-4f72-ac62-f497ffe6c15e
CREATED:
- Fexpr
properties
ID: 9c02fb15-967b-4294-a8ac-1327f1ec0de1
CREATED:
1.19. History
properties
ID: fb444369-a3e2-4451-8afc-e29571e706de
CREATED:
1.19.1. T
properties
ID: 3951ac2e-dc3d-4c25-b0ab-7b1daac53b47
CREATED:
- interesting to note the dualities in 'truthiness' across different runtimes. 'YES' 'NO', 'TRUE' 'FALSE', 1 0, 'OK' 'ERR'
1.19.2. CAR and CDR
properties
ID: 377a92dd-8e6e-4183-bd8a-70c47902d4d8
CREATED:
1.19.3. LAP  asm
properties
ID: f8f4d3ea-663a-4a8e-a9a8-f0d7813c710f
CREATED:
The LISP 2 Assembly Program
1.19.4. NASA
properties
CREATED:
ID: b5bb2fc8-df98-4c2e-9b83-e3fb6d3ff9ab
edges
– Ames AI Branch 1992 Report
– Coordinating Complex Problem-Solving Among Distributed Intelligent Agents
There are several famous Lisp stories retold by some JPL OGs - interesting stuff. What is less-known is the general infrastructure, ops, and planning software which Common Lisp was used for.
For my part I am less interested in the remote debugger and JPL side of things, but extremely interested in the Mission Control and network-based planning systems mentioned in various places.
See also: Working Notes from The 1992 AAAI Spring Symposium on Practical Approaches to Scheduling
- GERRY
properties
CREATED:
ID: 9fbbcfa5-1ac5-4e2a-b807-b6cadd05653bGERRY was an intelligent, rule-based scheduling system deployed at the NASA Ames Research Center to aid test engineers and human schedulers.
1.19.5. Foreign Function Interface
properties
ID: 203517c3-8324-471e-b932-56ead04d8e1a
CREATED:
AKA: FFI
Originally a term from the Common Lisp spec 😮
1.20. Books
properties
ID: 04d98054-94f2-47d1-8af4-751c10827ee8
CREATED:
1.20.1. PAIP
properties
ID: 91c00d39-6541-4b29-8d6b-a5b8c770cab0
CREATED:
Paradigms of Artificial Intelligence Programming by Peter Norvig
1.20.2. PCL
properties
ID: 53d96196-24d4-4737-93d0-a282f2cf5c0b
CREATED:
Practical Common Lisp - Peter Seibel
1.20.3. LoL
properties
ID: 11b9f51e-4d47-41ba-814f-aa6738a65881
CREATED:
Let Over Lambda by Doug Hoyte
1.20.4. Land of Lisp
properties
ID: 2b73b4e2-495a-4af0-9777-294196ad7f4d
CREATED:
1.21. Package Managers
properties
ID: d41019fd-ca88-4608-af00-9e7a84dcd49f
CREATED:
- Quicklisp is the defacto standard
- ASDF compatibility is assumed
- Package and System namespace separation is a problem
1.21.1. Qlot
properties
ID: e310d8ec-2a13-4a8e-aa15-db29738656b9
CREATED:
1.21.2. Vend
properties
ID: 6027aa9f-e3f6-4cf8-8c20-caef166a5126
CREATED:
1.21.3. OCICL
properties
ID: 1f1a5a5d-de86-461f-a209-9d81298d9a7c
CREATED:
edges
– [BROKEN LINK: github:ocicl/ocicl]
An OCI-based ASDF system distribution and management tool for Common Lisp
1.21.4. Quicklisp
properties
ID: 0b568dbe-fc89-4ce6-be86-fd18d1d2d5c0
CREATED:
Quicklisp is a library manager for Common Lisp. It works with your existing Common Lisp implementation to download, install, and load any of over 1,500 libraries with a few simple commands.
- quicklisp/quicklisp-controller: The software to build Quicklisp dists.
- quicklisp/quicklisp-projects: Metadata for projects tracked by Quicklisp.
- quicklisp/quicklisp-client: Quicklisp client.
- see also Shinmera's Shirakumo/redist: A project to handle the creation of Quicklisp dists
- with a nice html page for the dist: shirakumo Distribution Index
- Ultralisp
properties
ID: 6cfca9d2-8d3d-4725-a08f-349e08fd44e3
CREATED:An alternative distribution for Quicklisp - tracks git branches.
2. Scheme  scm
properties
ID: cce00db3-1428-4380-aa5d-8d2ec767b873
CREATED:
2.1. Racket
properties
ID: 74140b0d-af83-4516-ac70-b62bfa3de68d
CREATED:
- Andersen, Chang, and Felleisen (2017) from the PLT guys at NEU - Racket
2.1.1. Contracts
properties
ID: c1fdfebb-0dec-420d-abf9-aec7a2de5633
CREATED:
2.1.2. Concurrency
properties
ID: 79ecc4f2-f223-4045-a31a-565192efaf49
CREATED:
2.2. Guile
properties
ID: 66e2ab9a-51e3-4360-b7ad-0b38eb0dd6e5
CREATED:
2.3. scsh
properties
ID: c37d4dc5-0b09-4908-ab0a-e36f51f7d624
CREATED:
A Unix shell embedded in scheme
3. Lisp Machine Lisp
properties
ID: e21c02a5-5039-42c2-8416-aa5d45e70cb6
CREATED:
Maclisp->Zetalisp
4. Elisp  emacs elisp el
properties
ID: 6c69c42b-3d0a-48bf-a5ad-43b350477387
CREATED:
AKA: Emacs Lisp
4.1. use-package
properties
ID: 42ffc518-9c9c-4c59-9145-233aa58c6362
CREATED:
Declarative package configuration for Emacs.
- single macro
- NOT a package manager
- isolates package configuration and loading
- use-package#Keyword extensions
4.3. Widgets
properties
ID: 95427021-7e0c-4657-9b70-a7ed874fe35a
CREATED:
(require 'widget)
(eval-when-compile
(require 'wid-edit))
(defvar widget-example-repeat)
(defun widget-example ()
"Create the widgets from the Widget manual."
(interactive)
(switch-to-buffer "*Widget Example*")
(kill-all-local-variables)
(make-local-variable 'widget-example-repeat)
(let ((inhibit-read-only t))
(erase-buffer))
(remove-overlays)
(widget-insert "Here is some documentation.\n\n")
(widget-create 'editable-field
:size 13
:format "Name: %v " ; Text after the field!
"My Name")
(widget-create 'menu-choice
:tag "Choose"
:value "This"
:help-echo "Choose me, please!"
:notify (lambda (widget &rest ignore)
(message "%s is a good choice!"
(widget-value widget)))
'(item :tag "This option" :value "This")
'(choice-item "That option")
'(editable-field :menu-tag "No option" "Thus option"))
(widget-create 'editable-field
:format "Address: %v"
"Some Place\nIn some City\nSome country.")
(widget-insert "\nSee also ")
(widget-create 'link
:notify (lambda (&rest ignore)
(widget-value-set widget-example-repeat
'("En" "To" "Tre"))
(widget-setup))
"other work")
(widget-insert
" for more information.\n\nNumbers: count to three below\n")
(setq widget-example-repeat
(widget-create 'editable-list
:entry-format "%i %d %v"
:notify
(lambda (widget &rest ignore)
(let ((old (widget-get widget
':example-length))
(new (length (widget-value widget))))
(unless (eq old new)
(widget-put widget ':example-length new)
(message "You can count to %d." new))))
:value '("One" "Eh, two?" "Five!")
'(editable-field :value "three")))
(widget-insert "\n\nSelect multiple:\n\n")
(widget-create 'checkbox t)
(widget-insert " This\n")
(widget-create 'checkbox nil)
(widget-insert " That\n")
(widget-create 'checkbox
:notify (lambda (&rest ignore) (message "Tickle"))
t)
(widget-insert " Thus\n\nSelect one:\n\n")
(widget-create 'radio-button-choice
:value "One"
:notify (lambda (widget &rest ignore)
(message "You selected %s"
(widget-value widget)))
'(item "One") '(item "Another One.")
'(item "A Final One."))
(widget-insert "\n")
(widget-create 'push-button
:notify (lambda (&rest ignore)
(if (= (length
(widget-value widget-example-repeat))
3)
(message "Congratulation!")
(error "Three was the count!")))
"Apply Form")
(widget-insert " ")
(widget-create 'push-button
:notify (lambda (&rest ignore)
(widget-example))
"Reset Form")
(widget-insert "\n")
(use-local-map widget-keymap)
(widget-setup))
widget-example
4.5. Display
properties
ID: dd393948-c526-4216-bf9b-5869a7121933
CREATED:
4.5.1. Ewoc  gui
properties
ID: 114b1269-7400-45a7-ac41-17032015ffaa
CREATED:
4.5.2. Native Widgets
properties
ID: 401e2cbd-2769-4c73-979e-ca98f4f6208c
CREATED:
4.5.3. SVG Images
properties
ID: c3aeb32d-5353-40e3-9817-c086f6beb58b
CREATED:
4.5.4. Icons
properties
ID: eb112a07-aef7-4369-81f3-a50282bad8cc
CREATED:
4.5.5. Buttons
properties
ID: 9aed2656-f389-4a2b-8425-f6eeb546e901
CREATED:
4.6. Faces
properties
ID: 291cd491-b88c-4d52-b500-e7cc3095b3f1
CREATED:
Emacs can display text in several different styles, called faces. Each face can specify various face attributes, such as the font, height, weight, slant, foreground and background color, and underlining or overlining. Most major modes assign faces to the text automatically, via Font Lock mode.
(describe-function 'list-faces-display)
list-faces-display is an interactive native-comp-function in ‘faces.el’. It is bound to C-<down-mouse-2> <df>. It can also be invoked from the menu: Edit → Text Properties. (list-faces-display &optional REGEXP) Inferred type: (function (&optional t) boolean) List all faces, using the same sample text in each. The sample text is a string that comes from the variable ‘list-faces-sample-text’. If REGEXP is non-nil, list only those faces with names matching this regular expression. When called interactively with a prefix argument, prompt for a regular expression using ‘read-regexp’. Probably introduced at or before Emacs version 19.17.
A “face” is a collection of graphical attributes for displaying text: font, foreground color, background color, optional underlining, etc. Faces control how Emacs displays text in buffers, as well as other parts of the frame such as the mode line.
4.7. Modes
properties
ID: 8e912802-3969-4352-9a13-25f434bb1402
CREATED:
4.7.1. Outline
properties
ID: e69bdfe7-3e00-4c67-a5ec-8cd86e117db8
CREATED:
4.7.2. Allout
properties
ID: 40e5417f-6830-4cb7-8353-4b5a7a08010c
CREATED:
A minor mode similar to Outline mode but with more features and different syntax.
Headings are denoted by the underscore character _ in a comment line
followed by a heading character - the simplest of which are the
alternating pair . and ,.
In allout-mode headings space is significant - it is used to determine the nesting level of each heading. Add a space to shift inward, delete a space (relative to the previous heading) to shift outward.
This is how an outline can look (but sans indentation) with stylish prefixes:
- Top level
.* A topic . + One level 3 subtopic . . One level 4 subtopic . . A second 4 subtopic . + Another level 3 subtopic . #1 A numbered level 4 subtopic . #2 Another . ! Another level 4 subtopic with a different distinctive bullet . #4 And another numbered level 4 subtopic
This would be an outline with stylish prefixes inhibited (but the numbered and other distinctive bullets retained):
- Top level
.* A topic . * One level 3 subtopic . * One level 4 subtopic . * A second 4 subtopic . * Another level 3 subtopic . #1 A numbered level 4 subtopic . #2 Another . ! Another level 4 subtopic with a different distinctive bullet . #4 And another numbered level 4 subtopic
Stylish and constant prefixes (as well as old-style prefixes) are always respected by the topic maneuvering functions, regardless of this variable setting.
`comment-start' strings that do not end in spaces are tripled in the header-prefix, and an `_' underscore is tacked on the end, to distinguish them from regular comment strings. `comment-start' strings that do end in spaces are not tripled, but an underscore is substituted for the space.
Allout outline mode is a minor mode that provides extensive outline oriented formatting and manipulation. It enables structural editing of outlines, as well as navigation and exposure. It also is specifically aimed at accommodating syntax-sensitive text like programming languages. (For example, see the allout code itself, which is organized as an allout outline.)
In addition to typical outline navigation and exposure, allout includes:
- topic-oriented authoring, including keystroke-based topic creation, repositioning, promotion/demotion, cut, and paste
- incremental search with dynamic exposure and reconcealment of hidden text
- adjustable format, so programming code can be developed in outline-structure
- easy topic encryption and decryption, symmetric or key-pair
- "Hot-spot" operation, for single-keystroke maneuvering and exposure control
- integral outline layout, for automatic initial exposure when visiting a file
- independent extensibility, using comprehensive exposure and authoring hooks
and many other features.
Distinctive bullets are not cycled when topics are shifted or otherwise automatically rebulleted, so their marking is persistent until deliberately changed. Their significance is purely by convention, however. Some conventions suggest themselves:
`(' - open paren – an aside or incidental point `?' - question mark – uncertain or outright question `!' - exclamation point/bang – emphatic `[' - open square bracket – meta-note, about item instead of item's subject `\"' - double quote – a quotation or other citation `=' - equal sign – an assignment, some kind of definition `^' - carat – relates to something above
Some are more elusive, but their rationale may be recognizable:
`+' - plus – pending consideration, completion `_' - underscore – done, completed `&' - ampersand – addendum, furthermore
\(Some other non-plain bullets have special meaning to the software. By default:
`~' marks encryptable topics – see `allout-topic-encryption-bullet' `#' marks auto-numbered bullets – see `allout-numbered-bullet'.)
See `allout-plain-bullets-string' for the standard, alternating bullets.
4.7.3. Org  org
properties
ID: cea03181-b97b-494d-b362-28056416469d
CREATED:
- Org Babel
properties
ID: 9cfcee92-d862-400f-a80f-7bb538b27b45
CREATED: - Org Export
properties
ID: d26e1dac-f9cc-47a0-9a61-f32463247ec9
CREATED:- HTML
properties
ID: 9cb4a1c7-4798-4ac9-8958-9e3d86673d95
CREATED:
- HTML
- Refile and Copy
properties
ID: f46c1c20-c958-4068-bf0c-bf6f4f77546f
CREATED: - org-info.js
properties
ID: 09edda89-63e0-4496-84eb-764fb9b0b7c3
CREATED: - Syntax  syn
properties
ID: e1ef06a0-2c19-44fe-9afc-c216671c9ca4
CREATED:Elements can be stratified into “headings”, “sections”, “greater elements”, and “lesser elements”, from broadest scope to narrowest. Along with objects, these sub-classes define categories of syntactic environments. Only headings, sections, property drawers, and planning lines are context-free1, 2, every other syntactic component only exists within specific environments. This is a core concept of the syntax.
Expanding on the stratification of elements, lesser elements are elements that cannot contain any other elements. As such, a paragraph is considered a lesser element. Greater elements can themselves contain greater elements or lesser elements. Sections contain both greater and lesser elements, and headings can contain a section and other headings.
- Blank lines are considered a part of a preceding element.
To simplify references to common collections of objects, we define two useful sets. The minimal set of objects refers to plain text, text markup, entities, LaTeX fragments, superscripts and subscripts. The standard set of objects refers to the entire set of objects, excluding citation references and table cells.
- Org Element API
properties
ID: bdf4ac96-f9a6-47ea-a27a-89a8d2b20ba7
CREATED: - Org Protocol
properties
ID: d0590d0b-4be3-447b-a549-1c927be0c745
CREATED:javascript:location.href = 'org-protocol://capture?' + new URLSearchParams({ template: "i", url: location.href, title: document.title, body: window.getSelection()})org-protocol-protocol-alist
4.8. Autotype
properties
ID: d0af9d29-bbcd-405c-8c48-e3e933d71b25
CREATED:
- Emacs Auto-Insert Text in New Files
- autoinsert
- hippie expand usually replaces dabbrev-expand
- hippie-expand-try-function-list
- executable-insert / executable-set-magic
- abbrevs
- dabbrevs
- dynamic abbrevs - write a few chars and expand something you wrote earlier
- tempo
-
(describe-function 'skeleton-insert)skeleton-insert is an autoloaded native-comp-function in ‘skeleton.el’. (skeleton-insert SKELETON &optional REGIONS STR) Insert the complex statement skeleton SKELETON describes very concisely. With optional second argument REGIONS, wrap first interesting point (‘_’) in skeleton around next REGIONS words, if REGIONS is positive. If REGIONS is negative, wrap REGIONS preceding interregions into first REGIONS interesting positions (successive ‘_’s) in skeleton. An interregion is the stretch of text between two contiguous marked points. If you marked A B C [] (where [] is the cursor) in alphabetical order, the 3 interregions are simply the last 3 regions. But if you marked B A [] C, the interregions are B-A, A-[], []-C. The optional third argument STR, if specified, is the value for the variable ‘str’ within the skeleton. When this is non-nil, the interactor gets ignored, and this should be a valid skeleton element. When done with skeleton, but before going back to ‘_’-point, add a newline (unless ‘skeleton-end-newline’ is nil or ‘_’-point is at end of line), and run the hook ‘skeleton-end-hook’. SKELETON is made up as (INTERACTOR ELEMENT ...). INTERACTOR may be nil if not needed, a prompt-string or an expression for complex read functions. If ELEMENT is a string or a character it gets inserted (see also ‘skeleton-transformation-function’). Other possibilities are: \n go to next line and indent according to mode, unless this is the first/last element of a skeleton and point is at bol/eol _ interesting point, interregion here - interesting point, no interregion interaction, overrides interesting point set by _ > indent line (or interregion if > _) according to major mode @ add position to ‘skeleton-positions’ & do next ELEMENT if previous moved point | do next ELEMENT if previous didn’t move point -NUM delete NUM preceding characters (see ‘skeleton-untabify’) resume: skipped, continue here if quit is signaled nil skipped After termination, point will be positioned at the last occurrence of - or at the first occurrence of _ or at the end of the inserted text. Note that \n as the last element of the skeleton only inserts a newline if not at eol. If you want to unconditionally insert a newline at the end of the skeleton, use "\n" instead. Likewise with \n as the first element when at bol. Further elements can be defined via ‘skeleton-further-elements’. ELEMENT may itself be a SKELETON with an INTERACTOR. The user is prompted repeatedly for different inputs. The SKELETON is processed as often as the user enters a non-empty string. C-g terminates skeleton insertion, but continues after ‘resume:’ and positions at ‘_’ if any. If INTERACTOR in such a subskeleton is a prompt-string which contains a ".. %s .." it is formatted with ‘skeleton-subprompt’. Such an INTERACTOR may also be a list of strings with the subskeleton being repeated once for each string. Quoted Lisp expressions are evaluated for their side-effects. Other Lisp expressions are evaluated and the value treated as above. Note that expressions may not return t since this implies an endless loop. Modes can define other symbols by locally setting them to any valid skeleton element. The following local variables are available: str first time: read a string according to INTERACTOR then: insert previously read string once more help help-form during interaction with the user or nil input initial input (string or cons with index) while reading str v1, v2 local variables for memorizing anything you want Probably introduced at or before Emacs version 22.1.(define-skeleton local-variables-section "Insert a local variables section. Use current comment syntax if any." (completing-read "Mode: " obarray (lambda (symbol) (if (commandp symbol) (string-match "-mode$" (symbol-name symbol)))) t) '(save-excursion (if (re-search-forward page-delimiter nil t) (error "Not on last page"))) comment-start "Local Variables:" comment-end \n comment-start "mode: " str & -5 | '(kill-line 0) & -1 | comment-end \n ( (completing-read (format "Variable, %s: " skeleton-subprompt) obarray (lambda (symbol) (or (eq symbol 'eval) (custom-variable-p symbol))) t) comment-start str ": " (read-from-minibuffer "Expression: " nil read-expression-map nil 'read-expression-history) | _ comment-end \n) resume: comment-start "End:" comment-end \n)
6. Arc
properties
ID: 2094bd8c-4a95-4430-a126-9a56255380f4
CREATED:
7. MLisp
properties
ID: b7c0c96b-2555-4436-9231-42670db24838
CREATED:
7.1. M-expression
properties
ID: c32b20a7-11fc-4ab6-ae55-cc121b423a66
CREATED:
History of Lisp
The project of defining M-expressions precisely and compiling them or at least translating them into S-expressions was neither finalized nor explicitly abandoned. It just receded into the indefinite future, and a new generation of programmers appeared who preferred internal notation to any FORTRAN-like or ALGOL-like notation that could be devised.
8. CGOL
properties
ID: f49136cd-0a8e-412b-9fc0-75afb70502e2
CREATED:
mm in cgol:
for i in 1 to n do
for k in 1 to n do
(ac := 0;
for j in 1 to n do
ac := ac + a(i,j)*b(j,k);
c(i,k) := ac)
9. Cursed Lisp  cc
properties
ID: 22821eaa-7457-4dfd-b150-cd5835ae05d4
CREATED:
The designated name for the specific flavor of Common Lisp used and developed by The Compiler Company.
Our language is cursed because it is non-portable - as in the language provided is not built with the typical Lisper's idea of portability. We do not limit ourselves to the CL ANSI specification, and never support implementations beyond our own selection of SBCL builds.
When using the term Cursed Lisp in place of Common Lisp we are most likely trying to highlight specific capabilities of the Cursed Lisp environment which should not be considered in a 'pure ANSI CL' context.
Similarly, when referring to a language with the prefix Cursed like Cursed C or Cursed Rust, we are referring to our internal syntax specifications of these languages which have a special relationship with Cursed Lisp and contain 'symbolic bridges' between each other.