The nytpu.lisp-utils Reference Manual

This is the nytpu.lisp-utils Reference Manual, version 2.0.0, generated automatically by Declt version 4.0 beta 2 "William Riker" on Sun Dec 15 07:11:13 2024 GMT+0.

Table of Contents


1 Introduction


2 Systems

The main system appears first, followed by any subsystem dependency.


2.1 nytpu.lisp-utils

A collection of miscellaneous standalone utility packages.

Author

nytpu <>

Home Page

https://sr.ht/~nytpu/nytpu.lisp-utils

Source Control

(GIT https://git.sr.ht/~nytpu/nytpu.lisp-utils)

License

MPL-2.0

Version

2.0.0

Source

nytpu.lisp-utils.asd.

Child Components

3 Files

Files are sorted by type and then listed depth-first from the systems components trees.


3.1 Lisp


3.1.1 nytpu.lisp-utils/nytpu.lisp-utils.asd

Source

nytpu.lisp-utils.asd.

Parent Component

nytpu.lisp-utils (system).

ASDF Systems

nytpu.lisp-utils.


3.1.2 nytpu.lisp-utils/bind.lisp

Source

nytpu.lisp-utils.asd.

Parent Component

nytpu.lisp-utils (system).

Packages

nytpu.lisp-utils.bind.

Public Interface
Internals

3.1.3 nytpu.lisp-utils/shorthand-lambdas.lisp

Source

nytpu.lisp-utils.asd.

Parent Component

nytpu.lisp-utils (system).

Packages

nytpu.lisp-utils.shorthand-lambdas.

Public Interface
Internals

3.1.4 nytpu.lisp-utils/nytpu.lisp-utils.lisp

Dependency

shorthand-lambdas.lisp (file).

Source

nytpu.lisp-utils.asd.

Parent Component

nytpu.lisp-utils (system).

Packages

nytpu.lisp-utils.

Public Interface

4 Packages

Packages are listed by definition order.


4.1 nytpu.lisp-utils.bind

Source

bind.lisp.

Use List

common-lisp.

Public Interface
Internals

4.2 nytpu.lisp-utils.shorthand-lambdas

Source

shorthand-lambdas.lisp.

Use List

common-lisp.

Public Interface
Internals

4.3 nytpu.lisp-utils

Source

nytpu.lisp-utils.lisp.

Use List

common-lisp.

Public Interface

5 Definitions

Definitions are sorted by export status, category, package, and then by lexicographic order.


5.1 Public Interface


5.1.1 Macros

Macro: bind (bindings &body body)

Flexible lexical binding macro. Same structure as a LET/LET*, but allows destructuring and multiple values, binding local functions like FLET/LABELS, and calling arbitrary WITH-<> functions.

The main syntax of BIND is identical to LET, with symbols on their own or alone in parentheses being bound to NIL, and symbols with a form are bound to the result of that form. However, if a binding has multiple symbols in a row with a final form, each symbol be bound to a multiple return value, as in MULTIPLE-VALUE-BIND. Symbols wrapped in a list will have the result of form be destructuted as in DESTRUCTURING-BIND. S-exps beginning with :WITH will be wrapped around the BODY unmodified (other than the leading :WITH being removed), to allow for using arbitrary binding-creating macros like WITH-OPEN-FILE. S-exps beginning with :λ or :LAMBDA will be treated like FLET and the :λ should be followed by a name, lambda list, and body of the lambda.

Like a LET, the names bound by BIND are (conceptually) bound "in parallel" and cannot reference each other; and functions are bound as with FLET (i.e. they cannot reference themselves either). Note that as :WITH bindings are arbitrary binding-creating macros, they are not bound in parallel and can technically be accessed by some subset of the other bindings (doing so is bad practice as the :WITH’s accessibility to other bindings is undefined and may change).

*Standard* DECLARE statements (i.e. specified in the CLHS) are handled properly, and declarations referencing variables defined in the BIND are "hoisted" to the correct scope where the variables are actually declared in the macroexpansion—no matter what order they’re declared in or if they’re consolidated into one declare statement. Note that nonstandard declarations may or may not function properly (although a best-effort is made, and all the ones I’ve encountered work).

Example usage:
(bind (;; traditional LET-style bindings
a (b) ; null bindings that are bound to NIL
(c 1)
(d 2)

;; multiple value bindings
(e f (values 3 4))
(g h i (values 5 6 7))

;; list destructuring
((j (k) l) ’(8 (9) 10))

;; using arbitrary binding-creating macros
(:with with-output-to-string (str))

;; binding lambdas
(:λ foo ()
(values 11 12))
(:lambda bar (&rest vals)
(format str "~{~a~^, ~}" vals))

;; Accessors, including a shorthand for the full (symbol-macro-name accessor-function) syntax ;; like WITH-SLOTS has.
(:accessors (reader1 (reader2 reader2)) baz))
(bar a b c d e f g h i j k (foo)))
=> "NIL, NIL, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12"

Here is a full description of the syntax:
;; Full use of BIND. all BINDINGs will be visible in BODY
binding-form = ( "bind" ( binding* ) declaration* body* )

binding = null-binding | normal-binding | mv-binding | ds-binding | lambda-binding | accessors-binding | with-binding

;; binds to NIL, as in a normal LET
null-binding = symbol | ( symbol )

;; binds symbol to the result of evaluating FORM, as in a normal LET
normal-binding = ( symbol form )

;; expands to (multiple-value-bind (symbol symbol+) form ...)
mv-binding = ( symbol symbol+ form )

;; expands to (destructuring-bind (ds-lambda-list) form ...)
ds-binding = ( ( ds-lambda-list ) form )

;; expands to (flet ((name (lambda-list) body*)) ...)
lambda-binding = ( { ":lambda" | ":λ" } name ( lambda-list ) body* )

;; expands to (with-accessors (accessor+) instance ...)
;; note that unlike in WITH-ACCESSORS, accessor+ can actually be just one symbol rather than a ;; (symbol accessor) pair, in which case it will be expanded to the full (symbol accessor) form ;; like WITH-SLOTS does
accessors-binding = ( ":accessors" (accessor+) instance )

;; expands to (function-name params* ...)
;; allows for use of arbitrary binding-creating macros.
with-binding = ( ":with" function-name params* )

Notes on the description of the grammar:
- () are literal parenthesis, not grouping
- {} are grouping operators
- + is one or more operator
- * is zero or more operator
- | is alternation operator
- quotes indicates literal text
- ... in comments indicates that the remainder of the body and other bindings will be placed there. - symbol means a symbol that could be bound with LET in the same context
- form means any evaluatable form
- lambda-list means a standard lambda list
- ds-lambda-list means a destructuring lambda list as described in the CLHS
- params means to any acceptable parameters to the given function-name

Heavily inspired by:
- Scott L. Burson’s "New Let": https://gitlab.common-lisp.net/misc-extensions/devel/-/blob/master/src/new-let.lisp
- Ron Garret’s BINDING-BLOCK: https://github.com/rongarret/ergolib/blob/master/core/binding-block.lisp
(readers will note that it’s basically just features from the above macros but in a syntax I personally prefer, and also not shadowing stuff from COMMON-LISP).

Package

nytpu.lisp-utils.bind.

Source

bind.lisp.

Macro: bind* (bindings &body body)

Equivalent to BIND, however bindings are bound sequentially, as with a LET*. Lambda bindings are also done with LABELS instead of FLET, so they can reference themselves as well as prior bindings.

To hopefully slightly improve efficiency, BIND automatically condenses "runs" of null/normal bindings into one LET*, and runs of lambdas into one LABELS. All other bindings expand to repeatedly nested MULTIPLE-VALUE-BIND, DESTRUCTURING-BIND, etc.; and those will break up what otherwise would’ve been one LET* into multiple statements. The nesting order is preserved to ensure they behave sequentially as expected.

Package

nytpu.lisp-utils.bind.

Source

bind.lisp.

Macro: enable-commented-sexps (&optional copy-readtable)

Enable the #; reader macro character to comment a full s-expression. If COPY-READTABLE is T, then *READTABLE* will be copied with COPY-READTABLE before adding the reader macro.

When enabled, prefixing any form (s-expression or atom) with #; will comment it out. Note that the form must be valid according to the reader (albiet with *READ-SUPPRESS* true), but is otherwise not parsed in any way.

Package

nytpu.lisp-utils.

Source

nytpu.lisp-utils.lisp.

Macro: enable-shorthand-lambdas (&optional copy-readtable)

Enable the ^ reader macro character for shorthand lambdas in the current readtable. If COPY-READTABLE is T, then *READTABLE* will be copied with COPY-READTABLE before adding the reader macro.

When enabled, prefixing a form with ^ will implicitly wrap it in a LAMBDA, i.e.
^(...) → (lambda () ...). Inside that form, an $ symbol will insert a new argument. A symbol of format $number will (re)use that argument (arguments are one-indexed). A numbered argument must be either one past the newest argument which introduces a new argument, or an existing argument.

Examples:
(^(+ $ $) 2 2)
; → 4

(mapcar ^(+ $1 $1) ’(1 2 3 4)) and (mapcar ^(+ $ $1) ’(1 2 3 4))
; → (2 4 6 8)

(^(list $ $ ’c $ $2 $1) ’a ’b ’d)
; → (a b c d b a)

Package

nytpu.lisp-utils.shorthand-lambdas.

Source

shorthand-lambdas.lisp.

Macro: enable-syntaxes (&optional copy-readtable)

Enable all syntax extensions in the NYTPU.LISP-UTILS system, currently: SHORTHAND-LAMBDAS and COMMENT-SEXPS. When COPY-READTABLE is T, then the default readtable will be copied before adding new syntax.

Package

nytpu.lisp-utils.

Source

nytpu.lisp-utils.lisp.

Macro: handler-case-one (handler &rest body)

Given a single condition handler of the same format given to HANDLER-CASE, wrap BODY in a HANDLER-CASE form with just that exception handler.

Package

nytpu.lisp-utils.

Source

nytpu.lisp-utils.lisp.

Macro: restart-case-one (restart &rest body)

Given a single restart of the same format given to RESTART-CASE, wrap BODY in a RESTART-CASE form with just that exception handler.

Package

nytpu.lisp-utils.

Source

nytpu.lisp-utils.lisp.

Macro: togglef (&rest places)

Given a list of places, expand to a SETF form consisting of each place being set to (NOT place).

Package

nytpu.lisp-utils.

Source

nytpu.lisp-utils.lisp.


5.1.2 Ordinary functions

Function: all-equal? (predicate items)

Test if all members of ITEMS are equal to each other accoring to PREDICATE.

Package

nytpu.lisp-utils.

Source

nytpu.lisp-utils.lisp.

Function: alleq (&rest items)

Test if all the given ITEMS are EQ.

Package

nytpu.lisp-utils.

Source

nytpu.lisp-utils.lisp.

Function: alleql (&rest items)

Test if all the given ITEMS are EQL.

Package

nytpu.lisp-utils.

Source

nytpu.lisp-utils.lisp.

Function: allequal (&rest items)

Test if all the given ITEMS are EQUAL.

Package

nytpu.lisp-utils.

Source

nytpu.lisp-utils.lisp.

Function: allequalp (&rest items)

Test if all the given ITEMS are EQUALP.

Package

nytpu.lisp-utils.

Source

nytpu.lisp-utils.lisp.

Function: commented-sexp-reader (stream char arg)

Read a commented s-expression: just read a form, discard it, and return no values.

Package

nytpu.lisp-utils.

Source

nytpu.lisp-utils.lisp.

Function: match? (predicate item potential-matches)

Test if ITEM is a member of potential-matches according to PREDICATE.

Package

nytpu.lisp-utils.

Source

nytpu.lisp-utils.lisp.

Function: matcheq (item &rest potential-matches)

Test if ITEM is EQ to any of the other given items.

Package

nytpu.lisp-utils.

Source

nytpu.lisp-utils.lisp.

Function: matcheql (item &rest potential-matches)

Test if ITEM is EQL to any of the other given items.

Package

nytpu.lisp-utils.

Source

nytpu.lisp-utils.lisp.

Function: matchequal (item &rest potential-matches)

Test if ITEM is EQUAL to any of the other given items.

Package

nytpu.lisp-utils.

Source

nytpu.lisp-utils.lisp.

Function: matchequalp (item &rest potential-matches)

Test if ITEM is EQUALP to any of the other given items.

Package

nytpu.lisp-utils.

Source

nytpu.lisp-utils.lisp.

Function: nmapcar (function &rest lists)

Equivalent to MAPCAR, but destructively modify the first list in LISTS. Same semantics as MAPCAR: "FUNCTION is applied to the first element of each list, then to the second element of each list, and so on. The iteration terminates when the shortest list runs out, and excess elements in other lists are ignored. The value returned by MAPCAR is a list of the results of successive calls to FUNCTION." Perfect for pointless optimization of something really minor but still annoying!

Package

nytpu.lisp-utils.

Source

nytpu.lisp-utils.lisp.

Function: shorthand-lambda-reader (stream char)

Read a shorthand lambda: read one s-expression, wrap it in a lambda, and replace the arguments determined by $ and $num

Package

nytpu.lisp-utils.shorthand-lambdas.

Source

shorthand-lambdas.lisp.

Function: subvec (vec &optional start end displace-to-root)

Return a displaced vector that’s displaced into VEC containing the elements in range
[start, end], equivalent a non-copying SUBSEQ.

If VEC itself is displaced and DISPLACE-TO-ROOT is T, recursively finds the root vector and then displaces directly into that object (taking into account the offsets of the displacements leading to VEC). Returns the root vector itself if START is the first element and END is the last element of the root vector.

Package

nytpu.lisp-utils.

Source

nytpu.lisp-utils.lisp.


5.2 Internals


5.2.1 Ordinary functions

Function: add-new-arg (args args-len)
Package

nytpu.lisp-utils.shorthand-lambdas.

Source

shorthand-lambdas.lisp.

Function: analyze-declarations (decls)

Return an alist associating variable names with a declaration acting on that variable name, and a list of "free" declarations that don’t affect any variable.

Package

nytpu.lisp-utils.bind.

Source

bind.lisp.

Function: condense-all (bindings)

Given a list of bindings as from TRANSFORM-BINDINGS, condense all :NORMAL-BINDING and :NULL-BINDINGs into a single list, all :LAMBDA-BINDINGs into a single list, and return those two lists and the items from BINDINGS in the order they were previously, but with the bindings collected into the other lists filtered out.

Package

nytpu.lisp-utils.bind.

Source

bind.lisp.

Function: create-gensym-alist (names)

Given a list of symbols, return an alist associating each with a unique uninterned symbol.

Package

nytpu.lisp-utils.bind.

Source

bind.lisp.

Function: find-binding-run (kind bindings)

Given a KIND as from MATCH-BINDING-KIND and a list of BINDINGS, return a list of bindings that are a consecutive run of KIND operated on with TRANSFORM-BINDING; and then returns the remaining bindings after that consecutive run. If the first value is NIL—i.e. there are no consecutive bindings—then the second value will simply be BINDINGS.

Package

nytpu.lisp-utils.bind.

Source

bind.lisp.

Function: get-binding-declarations (names decls)

Given a list of variable names as from GET-BINDING-NAMES and an alist of declarations as from ANALYZE-DECLARATIONS, return a list of declarations that apply to members of that run, mutated into proper declaration form (i.e. the variable name is appended) and a list of the plain original alist pairs from DECLS.

Package

nytpu.lisp-utils.bind.

Source

bind.lisp.

Function: get-binding-names (binding)

Given a single transformed binding as from TRANSFORM-BINDINGS, return a list of all variable names declared in that binding. **Does not support :WITH-BINDING** and always returns NIL, those are considered opaque macros and are not analyzed.

Package

nytpu.lisp-utils.bind.

Source

bind.lisp.

Function: get-name-declarations (name decls)

Given a variable name and an alist of declarations, return all pairs from the alist whose CAR is EQL to NAME.

Package

nytpu.lisp-utils.bind.

Source

bind.lisp.

Function: match-binding-kind (binding)

Given a single BINDING, return the kind of binding it is as a keyword (see formal grammar in BIND’s docstring).

Package

nytpu.lisp-utils.bind.

Source

bind.lisp.

Function: replace-names (binding to-replace)

Given a BINDING as from TRANSFORM-BINDINGs and an alist pairing names (as from GET-BINDING-NAMES) to alternate values, replace all symbols that would’ve been bound in BINDING to their alternate value from the alist.

Package

nytpu.lisp-utils.bind.

Source

bind.lisp.

Function: replace-shorthand (form existing-args existing-args-len)

Given a FORM, list of existing arguments, and optionally the length of EXISTING-ARGS, parse if FORM is a dollar sign shorthand argument ($ or $x). Recursively applies itself to any sublists in FORM and returns *all* accumulated arguments and the proper length.

Returns three values:
- A new GENSYM’d symbol if it is a shorthand argument or FORM itself otherwise.
- The EXISTING-ARGS list, with the GENSYM’d symbol added on front if it is a shorthand argument. - The length of the returned list whether or not it had a symbol added.

Package

nytpu.lisp-utils.shorthand-lambdas.

Source

shorthand-lambdas.lisp.

Function: rewrite-alist (alist)

Given an alist, return a copy where each pair of values is rewritten as a list.

Package

nytpu.lisp-utils.bind.

Source

bind.lisp.

Function: separate-declarations (body)

Given a list of body forms, return all the declarations in the order they’re given and the remaining body forms.

Package

nytpu.lisp-utils.bind.

Source

bind.lisp.

Function: transform-binding (binding &optional kind)

Given a BINDING and optionally its precomputed KIND, transform it to the "native" form taken by that BINDING’s lower-level macro, e.g. the parameters to LET* or LABELS.

Package

nytpu.lisp-utils.bind.

Source

bind.lisp.

Function: transform-bindings (bindings)

Given a list of bindings as given to BIND, transform them with TRANSFORM-BINDING and condense runs as necessary, then return the list in reverse order with each sublist prefixed by their kind as from MATCH-BINDING-KIND.

Package

nytpu.lisp-utils.bind.

Source

bind.lisp.


Appendix A Indexes


A.1 Concepts


A.2 Functions

Jump to:   A   B   C   E   F   G   H   M   N   R   S   T  
Index Entry  Section

A
add-new-arg: Private ordinary functions
all-equal?: Public ordinary functions
alleq: Public ordinary functions
alleql: Public ordinary functions
allequal: Public ordinary functions
allequalp: Public ordinary functions
analyze-declarations: Private ordinary functions

B
bind: Public macros
bind*: Public macros

C
commented-sexp-reader: Public ordinary functions
condense-all: Private ordinary functions
create-gensym-alist: Private ordinary functions

E
enable-commented-sexps: Public macros
enable-shorthand-lambdas: Public macros
enable-syntaxes: Public macros

F
find-binding-run: Private ordinary functions
Function, add-new-arg: Private ordinary functions
Function, all-equal?: Public ordinary functions
Function, alleq: Public ordinary functions
Function, alleql: Public ordinary functions
Function, allequal: Public ordinary functions
Function, allequalp: Public ordinary functions
Function, analyze-declarations: Private ordinary functions
Function, commented-sexp-reader: Public ordinary functions
Function, condense-all: Private ordinary functions
Function, create-gensym-alist: Private ordinary functions
Function, find-binding-run: Private ordinary functions
Function, get-binding-declarations: Private ordinary functions
Function, get-binding-names: Private ordinary functions
Function, get-name-declarations: Private ordinary functions
Function, match-binding-kind: Private ordinary functions
Function, match?: Public ordinary functions
Function, matcheq: Public ordinary functions
Function, matcheql: Public ordinary functions
Function, matchequal: Public ordinary functions
Function, matchequalp: Public ordinary functions
Function, nmapcar: Public ordinary functions
Function, replace-names: Private ordinary functions
Function, replace-shorthand: Private ordinary functions
Function, rewrite-alist: Private ordinary functions
Function, separate-declarations: Private ordinary functions
Function, shorthand-lambda-reader: Public ordinary functions
Function, subvec: Public ordinary functions
Function, transform-binding: Private ordinary functions
Function, transform-bindings: Private ordinary functions

G
get-binding-declarations: Private ordinary functions
get-binding-names: Private ordinary functions
get-name-declarations: Private ordinary functions

H
handler-case-one: Public macros

M
Macro, bind: Public macros
Macro, bind*: Public macros
Macro, enable-commented-sexps: Public macros
Macro, enable-shorthand-lambdas: Public macros
Macro, enable-syntaxes: Public macros
Macro, handler-case-one: Public macros
Macro, restart-case-one: Public macros
Macro, togglef: Public macros
match-binding-kind: Private ordinary functions
match?: Public ordinary functions
matcheq: Public ordinary functions
matcheql: Public ordinary functions
matchequal: Public ordinary functions
matchequalp: Public ordinary functions

N
nmapcar: Public ordinary functions

R
replace-names: Private ordinary functions
replace-shorthand: Private ordinary functions
restart-case-one: Public macros
rewrite-alist: Private ordinary functions

S
separate-declarations: Private ordinary functions
shorthand-lambda-reader: Public ordinary functions
subvec: Public ordinary functions

T
togglef: Public macros
transform-binding: Private ordinary functions
transform-bindings: Private ordinary functions


A.3 Variables