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.
The main system appears first, followed by any subsystem dependency.
nytpu.lisp-utils
A collection of miscellaneous standalone utility packages.
nytpu <alex@nytpu.com>
(GIT https://git.sr.ht/~nytpu/nytpu.lisp-utils)
MPL-2.0
2.0.0
bind.lisp
(file).
shorthand-lambdas.lisp
(file).
nytpu.lisp-utils.lisp
(file).
Files are sorted by type and then listed depth-first from the systems components trees.
nytpu.lisp-utils/nytpu.lisp-utils.asd
nytpu.lisp-utils/bind.lisp
nytpu.lisp-utils/shorthand-lambdas.lisp
nytpu.lisp-utils/nytpu.lisp-utils.lisp
nytpu.lisp-utils/nytpu.lisp-utils.asd
nytpu.lisp-utils
(system).
nytpu.lisp-utils/bind.lisp
nytpu.lisp-utils
(system).
analyze-declarations
(function).
condense-all
(function).
create-gensym-alist
(function).
find-binding-run
(function).
get-binding-declarations
(function).
get-binding-names
(function).
get-name-declarations
(function).
match-binding-kind
(function).
replace-names
(function).
rewrite-alist
(function).
separate-declarations
(function).
transform-binding
(function).
transform-bindings
(function).
nytpu.lisp-utils/shorthand-lambdas.lisp
nytpu.lisp-utils
(system).
enable-shorthand-lambdas
(macro).
shorthand-lambda-reader
(function).
add-new-arg
(function).
replace-shorthand
(function).
nytpu.lisp-utils/nytpu.lisp-utils.lisp
shorthand-lambdas.lisp
(file).
nytpu.lisp-utils
(system).
all-equal?
(function).
alleq
(function).
alleql
(function).
allequal
(function).
allequalp
(function).
commented-sexp-reader
(function).
enable-commented-sexps
(macro).
enable-syntaxes
(macro).
handler-case-one
(macro).
match?
(function).
matcheq
(function).
matcheql
(function).
matchequal
(function).
matchequalp
(function).
nmapcar
(function).
restart-case-one
(macro).
subvec
(function).
togglef
(macro).
Packages are listed by definition order.
nytpu.lisp-utils.bind
common-lisp
.
analyze-declarations
(function).
condense-all
(function).
create-gensym-alist
(function).
find-binding-run
(function).
get-binding-declarations
(function).
get-binding-names
(function).
get-name-declarations
(function).
match-binding-kind
(function).
replace-names
(function).
rewrite-alist
(function).
separate-declarations
(function).
transform-binding
(function).
transform-bindings
(function).
nytpu.lisp-utils.shorthand-lambdas
common-lisp
.
enable-shorthand-lambdas
(macro).
shorthand-lambda-reader
(function).
add-new-arg
(function).
replace-shorthand
(function).
nytpu.lisp-utils
common-lisp
.
all-equal?
(function).
alleq
(function).
alleql
(function).
allequal
(function).
allequalp
(function).
commented-sexp-reader
(function).
enable-commented-sexps
(macro).
enable-syntaxes
(macro).
handler-case-one
(macro).
match?
(function).
matcheq
(function).
matcheql
(function).
matchequal
(function).
matchequalp
(function).
nmapcar
(function).
restart-case-one
(macro).
subvec
(function).
togglef
(macro).
Definitions are sorted by export status, category, package, and then by lexicographic order.
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).
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.
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.
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)
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.
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.
Given a single restart of the same format given to RESTART-CASE, wrap BODY in a RESTART-CASE form with just that exception handler.
Given a list of places, expand to a SETF form consisting of each place being set to (NOT place).
Test if all members of ITEMS are equal to each other accoring to PREDICATE.
Test if all the given ITEMS are EQ.
Test if all the given ITEMS are EQL.
Test if all the given ITEMS are EQUAL.
Test if all the given ITEMS are EQUALP.
Read a commented s-expression: just read a form, discard it, and return no values.
Test if ITEM is a member of potential-matches according to PREDICATE.
Test if ITEM is EQ to any of the other given items.
Test if ITEM is EQL to any of the other given items.
Test if ITEM is EQUAL to any of the other given items.
Test if ITEM is EQUALP to any of the other given items.
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!
Read a shorthand lambda: read one s-expression, wrap it in a lambda, and replace the arguments determined by $ and $num
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.
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.
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.
Given a list of symbols, return an alist associating each with a unique uninterned symbol.
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.
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.
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.
Given a variable name and an alist of declarations, return all pairs from the alist whose CAR is EQL to NAME.
Given a single BINDING, return the kind of binding it is as a keyword (see formal grammar in BIND’s docstring).
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.
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.
Given an alist, return a copy where each pair of values is rewritten as a list.
Given a list of body forms, return all the declarations in the order they’re given and the remaining body forms.
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.
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.
Jump to: | A B C E F G H M N R S T |
---|
Jump to: | A B C E F G H M N R S T |
---|
Jump to: | B F N P S |
---|
Jump to: | B F N P S |
---|