The dynamic-collect Reference Manual

Table of Contents

Next: , Previous: , Up: (dir)   [Contents][Index]

The dynamic-collect Reference Manual

This is the dynamic-collect Reference Manual, generated automatically by Declt version 2.3 "Robert April" on Wed Mar 14 03:50:16 2018 GMT+0.


Next: , Previous: , Up: Top   [Contents][Index]

1 Introduction

                           DYNAMIC-COLLECT
                           ===============

                           By Robert Smith

DYNAMIC-COLLECT is a library for dynamic, continuable, and abortable
collection of data.

This code is useful for times when data needs to be collected at
various points in a program, but it is inconvenient to modify the
program and create new pipelines for passing data around. It is also
useful when such pipelines would take away from the intent of the
program.

This code was originally created for tasks in code analysis, where
warnings and errors were collected during the analysis, and then
processed a posteriori.


                               EXAMPLE
                               -------

First, we will define a function which intends to do some kind of
analysis of data, and warn if it's not the right type. In this case,
we will check that it's an integer. If it's not, we'll warn that we
wanted an integer. Actually, we will collect a message that represents
the warning.

(defun pass-1 (data)
  (unless (integerp data)
    (collect (format nil "Warning: Not an integer: ~S" data))))

Next, we will do a more stringent analysis. If the data is a non-null
list, then we will require that the first element of the list needs to
be a symbol. Perhaps this represents a function call. If the data
indeed doesn't look like a function call, then we will collect an
error, and specify that collection (and further analysis) must not
continue, so we pass NIL to CONTINUEP.

(defun pass-2 (data)
  (when (and (listp data)
             (plusp (length data)))
    (unless (symbolp (car data))
      (collect (format nil "Error: A function call needs a symbol ~
                            in the first position, given: ~S"
                       (car data))
               :continuep nil))))

Now a simple function to process our collected messages. In this case,
we will just print them out in a friendly fashion.

(defun process-messages (messages)
  (if (null messages)
      (format t "No messages.~%")
      (format t "~@(~R~) message~:P:~%~{  >> ~A~%~}"
                (length messages)
                messages)))

Finally, we have our main entry point to our analysis. We use
WITH-DYNAMIC-COLLECTION, and do the passes on our data. We will log
when a pass completes to the user.

(defun main (data)
  (let ((messages (with-dynamic-collection ()
                    (pass-1 data)
                    (format t ";;; Done with pass 1.~%")
                    (force-output)
                    (pass-2 data)
                    (format t ";;; Done with pass 2.~%")
                    (force-output))))
    (process-messages messages)))

Now for some test runs. First, we provide completely "legitimate" data
(according to our passes).

CL-USER> (main 5)
;;; Done with pass 1.
;;; Done with pass 2.
No messages.
NIL

As seen, the passes complete, and we have no messages. Now let's do
the analysis on something that warns on the first pass.

CL-USER> (main :quux)
;;; Done with pass 1.
;;; Done with pass 2.
One message:
  >> Warning: Not an integer: :QUUX
NIL

As seen, both passes complete, but we ended up with a warning we
collected. Now let's do something that passes the second analysis, but
warns on the first, again.

CL-USER> (main '(hello))
;;; Done with pass 1.
;;; Done with pass 2.
One message:
  >> Warning: Not an integer: (HELLO)
NIL

Same thing. Finally, let's do something that will cause issues with
both.

CL-USER> (main '(5 hello))
;;; Done with pass 1.
Two messages:
  >> Warning: Not an integer: (5 HELLO)
  >> Error: A function call needs a symbol in the first position, given: 5
NIL

Note this time that both warnings were collected and displayed. But
more importantly, note that we never reached the end of the second
pass; our collection aborted early.

Despite this very contrived example, early termination is very
useful. For example, if we are analyzing a file that ends up being
unable to be parsed, we can collect an error message, and fail early.


                         ENSURING CORRECTNESS
                         --------------------

Using the variable *ENSURE-HANDLED-COLLECT*, we can error if the
system detects that a COLLECT is used without a properly enclosing
WITH-DYNAMIC-COLLECTION.

By default, *ENSURE-HANDLED-COLLECT* is NIL, which means that
unhandled COLLECT forms will just return their RETURN keyword
parameter value.


                    COMPOSING DYNAMIC COLLECTIONS
                    -----------------------------

WITH-DYNAMIC-COLLECTION is actually composable via the notion of
tags. A "tag" is an EQL-comparable thing (often a keyword) that lets
one match up a WITH-DYNAMIC-COLLECTION with a COLLECT form. We simply
provide tags to each, and collection will be matched up
accordingly. For example:

CL-USER> (format t "OUTER: ~S~%"
                 (with-dynamic-collection (:tag :outer)
                   (collect 1 :tag :outer)
                   (format t "INNER: ~S~%"
                           (with-dynamic-collection (:tag :inner)
                             (collect 2 :tag :outer)
                             (collect 3 :tag :inner)))))

will print

INNER: (3)
OUTER: (1 2)

as expected. By default, the tags are NIL (an EQL-comparable value),
which is sufficient when there's no composition.


Next: , Previous: , Up: Top   [Contents][Index]

2 Systems

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


Previous: , Up: Systems   [Contents][Index]

2.1 dynamic-collect

Author

Robert Smith <quad@symbo1ics.com>

License

BSD 3-clause (see LICENSE)

Description

A library for dynamic, continuable, and abortable collection.

Source

dynamic-collect.asd (file)

Components

Next: , Previous: , Up: Top   [Contents][Index]

3 Files

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


Previous: , Up: Files   [Contents][Index]

3.1 Lisp


Next: , Previous: , Up: Lisp files   [Contents][Index]

3.1.1 dynamic-collect.asd

Location

dynamic-collect.asd

Systems

dynamic-collect (system)


Next: , Previous: , Up: Lisp files   [Contents][Index]

3.1.2 dynamic-collect/package.lisp

Parent

dynamic-collect (system)

Location

package.lisp

Packages

dynamic-collect


Previous: , Up: Lisp files   [Contents][Index]

3.1.3 dynamic-collect/dynamic-collect.lisp

Dependency

package.lisp (file)

Parent

dynamic-collect (system)

Location

dynamic-collect.lisp

Exported Definitions
Internal Definitions

Next: , Previous: , Up: Top   [Contents][Index]

4 Packages

Packages are listed by definition order.


Previous: , Up: Packages   [Contents][Index]

4.1 dynamic-collect

Source

package.lisp (file)

Use List

common-lisp

Exported Definitions
Internal Definitions

Next: , Previous: , Up: Top   [Contents][Index]

5 Definitions

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


Next: , Previous: , Up: Definitions   [Contents][Index]

5.1 Exported definitions


Next: , Previous: , Up: Exported definitions   [Contents][Index]

5.1.1 Special variables

Special Variable: *ensure-handled-collect*

If T, ensure that COLLECT forms are inside WITH-DYNAMIC-COLLECTION. If NIL, return the specified RETURN value from COLLECT.

Package

dynamic-collect

Source

dynamic-collect.lisp (file)


Next: , Previous: , Up: Exported definitions   [Contents][Index]

5.1.2 Macros

Macro: with-dynamic-collection (&key TAG) &body BODY

Dynamically collect messages that were signalled during the execution of BODY from COLLECT. Return a list of messages in the order they were collected. If TAG is provided, then only COLLECT forms which have the same tag will be accrued.

Package

dynamic-collect

Source

dynamic-collect.lisp (file)


Previous: , Up: Exported definitions   [Contents][Index]

5.1.3 Functions

Function: collect DATA &key RETURN CONTINUEP TAG

Collect the data DATA in a WITH-DYNAMIC-COLLECTION
environment. Return the value RETURN from the form in the event the function is returned from.

If CONTINUEP is null, then collecting will cease and the
matching WITH-DYNAMIC-COLLECTION form will return.

The TAG denotes at which WITH-DYNAMIC-COLLECTION form the DATA will be accumulated.

Package

dynamic-collect

Source

dynamic-collect.lisp (file)


Previous: , Up: Definitions   [Contents][Index]

5.2 Internal definitions


Next: , Previous: , Up: Internal definitions   [Contents][Index]

5.2.1 Generic functions

Generic Function: messenger-continuep CONDITION
Package

dynamic-collect

Methods
Method: messenger-continuep (CONDITION messenger)
Source

dynamic-collect.lisp (file)

Generic Function: messenger-id CONDITION
Package

dynamic-collect

Methods
Method: messenger-id (CONDITION messenger)
Source

dynamic-collect.lisp (file)

Generic Function: messenger-payload CONDITION
Package

dynamic-collect

Methods
Method: messenger-payload (CONDITION messenger)
Source

dynamic-collect.lisp (file)

Generic Function: messenger-tag CONDITION
Package

dynamic-collect

Methods
Method: messenger-tag (CONDITION messenger)
Source

dynamic-collect.lisp (file)


Previous: , Up: Internal definitions   [Contents][Index]

5.2.2 Conditions

Condition: messenger ()

A condition to carry messages between parts of programs.

Package

dynamic-collect

Source

dynamic-collect.lisp (file)

Direct superclasses

condition (condition)

Direct methods
Direct slots
Slot: payload
Initargs

:payload

Readers

messenger-payload (generic function)

Slot: continuep
Initargs

:continuep

Initform

(quote t)

Readers

messenger-continuep (generic function)

Slot: id
Initargs

:id

Readers

messenger-id (generic function)

Slot: tag
Initargs

:tag

Initform

(quote nil)

Readers

messenger-tag (generic function)


Previous: , Up: Top   [Contents][Index]

Appendix A Indexes


Next: , Previous: , Up: Indexes   [Contents][Index]

A.1 Concepts

Jump to:   D   F   L  
Index Entry  Section

D
dynamic-collect.asd: The dynamic-collect<dot>asd file
dynamic-collect/dynamic-collect.lisp: The dynamic-collect/dynamic-collect<dot>lisp file
dynamic-collect/package.lisp: The dynamic-collect/package<dot>lisp file

F
File, Lisp, dynamic-collect.asd: The dynamic-collect<dot>asd file
File, Lisp, dynamic-collect/dynamic-collect.lisp: The dynamic-collect/dynamic-collect<dot>lisp file
File, Lisp, dynamic-collect/package.lisp: The dynamic-collect/package<dot>lisp file

L
Lisp File, dynamic-collect.asd: The dynamic-collect<dot>asd file
Lisp File, dynamic-collect/dynamic-collect.lisp: The dynamic-collect/dynamic-collect<dot>lisp file
Lisp File, dynamic-collect/package.lisp: The dynamic-collect/package<dot>lisp file

Jump to:   D   F   L  

Next: , Previous: , Up: Indexes   [Contents][Index]

A.2 Functions

Jump to:   C   F   G   M   W  
Index Entry  Section

C
collect: Exported functions

F
Function, collect: Exported functions

G
Generic Function, messenger-continuep: Internal generic functions
Generic Function, messenger-id: Internal generic functions
Generic Function, messenger-payload: Internal generic functions
Generic Function, messenger-tag: Internal generic functions

M
Macro, with-dynamic-collection: Exported macros
messenger-continuep: Internal generic functions
messenger-continuep: Internal generic functions
messenger-id: Internal generic functions
messenger-id: Internal generic functions
messenger-payload: Internal generic functions
messenger-payload: Internal generic functions
messenger-tag: Internal generic functions
messenger-tag: Internal generic functions
Method, messenger-continuep: Internal generic functions
Method, messenger-id: Internal generic functions
Method, messenger-payload: Internal generic functions
Method, messenger-tag: Internal generic functions

W
with-dynamic-collection: Exported macros

Jump to:   C   F   G   M   W  

Next: , Previous: , Up: Indexes   [Contents][Index]

A.3 Variables

Jump to:   *  
C   I   P   S   T  
Index Entry  Section

*
*ensure-handled-collect*: Exported special variables

C
continuep: Internal conditions

I
id: Internal conditions

P
payload: Internal conditions

S
Slot, continuep: Internal conditions
Slot, id: Internal conditions
Slot, payload: Internal conditions
Slot, tag: Internal conditions
Special Variable, *ensure-handled-collect*: Exported special variables

T
tag: Internal conditions

Jump to:   *  
C   I   P   S   T  

Previous: , Up: Indexes   [Contents][Index]

A.4 Data types

Jump to:   C   D   M   P   S  
Index Entry  Section

C
Condition, messenger: Internal conditions

D
dynamic-collect: The dynamic-collect system
dynamic-collect: The dynamic-collect package

M
messenger: Internal conditions

P
Package, dynamic-collect: The dynamic-collect package

S
System, dynamic-collect: The dynamic-collect system

Jump to:   C   D   M   P   S