The utilities.print-items Reference Manual

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

The utilities.print-items Reference Manual

This is the utilities.print-items Reference Manual, version 0.2.0, generated automatically by Declt version 4.0 beta 2 "William Riker" on Thu Sep 15 06:27:21 2022 GMT+0.

Table of Contents


1 Introduction

#+TITLE:       utilities.print-items README
#+AUTHOR:      Jan Moringen
#+EMAIL:       jmoringe@techfak.uni-bielefeld.de
#+DESCRIPTION: Composable, unreadable printing of objects
#+KEYWORDS:    print-items, composable printing, print-object, utilities
#+LANGUAGE:    en

#+OPTIONS: num:nil

* Introduction

  The =utilities.print-items= system provides a protocol for flexible
  and composable printing, primarily unreadable printing.

  Why is this useful? Common Lisp has the generic function
  ~cl:print-object~, which is often used to print compact and
  intuitive yet unreadable (by ~cl:read~) representations of
  objects. Thanks to CLOS, considerable flexibility and composability
  would, in principle, be achievable. However, a common idiom is

  #+BEGIN_SRC lisp
    (defmethod print-object ((object CLASS) stream)
      (print-unreadable-object (stream :type t :id t)
        CODE))
  #+END_SRC

  which prevents the flexibility provided by CLOS from actually being
  used:

  + Calling the next method in a ~print-object~ method would either
    wrap the final result in multiple layers of
    ~print-unreadable-object~ or some of the methods would not be
    fully functional on their own.

  + Similarly, ~:before~ and ~:after~ methods on ~print-object~ would
    produce output parts outside of the prefix and suffix produced by
    ~print-unreadable-object~.

  #+ATTR_HTML: :alt "build status image" :title Build Status :align right
  [[https://travis-ci.org/scymtym/utilities.print-items][https://travis-ci.org/scymtym/utilities.print-items.svg]]

* Tutorial

  To illustrate the problem and the solution offered by the
  =utilities.print-items= system more concretely, consider the
  following example:

  #+BEGIN_SRC lisp :exports both :results silent
    (defclass name-mixin ()
      ((%name :initarg :name :reader name)))

    (defclass value-mixin ()
      ((%value :initarg :value :reader value)))

    (defclass binding (name-mixin value-mixin)
      ())
  #+END_SRC

** The Problem

   Due to the issues mentioned [[*Introduction][above]], ~print-object~-based solutions
   are not satisfactory:

   #+BEGIN_SRC lisp :exports both :results value
     (defmethod print-object ((object name-mixin) stream)
       (format stream "~S" (name object))
       (when (next-method-p)
         (call-next-method)))

     (defmethod print-object ((object value-mixin) stream)
       (format stream "= ~S" (value object))
       (when (next-method-p)
         (call-next-method)))

     (princ-to-string (make-instance 'binding :name "foo" :value 5))
   #+END_SRC

   #+RESULTS:
   : "foo"= 5#

   This is somewhat composable and the output has all expected parts,
   but the arrangement of the output parts is completely wrong as well
   as hard to control.

   #+BEGIN_SRC lisp :exports results :results silent
     (ignore-errors
      (remove-method #'print-object (find-method #'print-object '() (list (find-class 'name-mixin) (find-class 't)))))
     (ignore-errors
      (remove-method #'print-object (find-method #'print-object '() (list (find-class 'value-mixin) (find-class 't)))))
   #+END_SRC

   The opposite approach would be:

   #+BEGIN_SRC lisp :exports both :results value
     (defmethod print-object ((object binding) stream)
       (print-unreadable-object (object stream :type t :identity t)
         (format stream "~S = ~S" (name object) (value object))))

     (princ-to-string (make-instance 'binding :name "foo" :value 5))
   #+END_SRC

   #+RESULTS:
   : #

   This produces the expected result but is not composable at all
   since every user of ~name-mixin~ and ~value-mixin~ has to do all
   the printing itself.

   #+BEGIN_SRC lisp :exports results :results silent
     (ignore-errors
      (remove-method #'print-object (find-method #'print-object '() (list (find-class binding) (find-class 't)))))
   #+END_SRC

** The Solution

   When using the =utilities.print-items= system, ~print-object~
   methods are replaced by ~print-items:print-items~ methods (note the
   ~append~ method combination) for mixin classes:

   #+BEGIN_SRC lisp :exports both :results value
     (defclass name-mixin ()
       ((%name :initarg :name :reader name)))

     (defmethod print-items:print-items append ((object name-mixin))
       `((:name "~S" ,(name object))))

     (defclass value-mixin ()
       ((%value :initarg :value :reader value)))

     (defmethod print-items:print-items append ((object value-mixin))
       `((:value "= ~S" ,(value object))))

     (defclass binding (value-mixin name-mixin)
       ())

     (defmethod print-object ((object binding) stream)
       (print-unreadable-object (object stream :type t :identity t)
         (print-items:format-items
          stream (print-items:effective-print-items object))))

     (princ-to-string (make-instance 'binding :name "foo" :value 5))
   #+END_SRC

   #+RESULTS:
   : #

   #+BEGIN_SRC lisp :exports results :results silent
     (ignore-errors
      (remove-method #'print-object (find-method #'print-object '() (list (find-class binding) (find-class 't)))))
   #+END_SRC

   This solves the problem of composability and getting all output
   parts between the prefix and suffix produced by
   ~print-unreadable-object~, but the arrangement of output parts is
   not ideal. We could improve the situation by tweaking the order of
   elements in the superclass list of ~binding~ but that would be
   intrusive and again not composable when, for example, subclasses of
   ~binding~ are defined. Furthermore, the ~print-object~ method does
   not do anything specific to ~binding~.

   The following adjustments solve both issues (changes in upper
   case):

   #+BEGIN_SRC lisp :exports both :results value
     (defmethod print-items:print-items append ((object value-mixin))
       `(((:value (:AFTER :NAME)) " = ~S" ,(value object))))

     (defclass binding (name-mixin value-mixin PRINT-ITEMS:PRINT-ITEMS-MIXIN)
       ())

     ;; no PRINT-OBJECT method for BINDING

     (princ-to-string (make-instance 'binding :name "foo" :value 5))
   #+END_SRC

   #+RESULTS:
   : #

   Constraints such as ~(:after :name)~ control the order of
   items. Constraints referring to absent items have no
   effect. Contradictory constraints cause an error to be signaled.

** Advanced Usage

*** Adjusting Items

    It is sometimes necessary to modify or suppress the print items
    produced for superclasses to get the desired printed
    representation. This can be achieved in two ways:

    1. By defining a ~print-items:print-items append~ method that
       returns replacements for the undesired items:

       #+BEGIN_SRC lisp :exports both :results value
         (defclass unnamed-binding (binding)
           ())

         (defmethod print-items:print-items append ((object unnamed-binding))
           `((:name "«unnamed»")))

         (princ-to-string (make-instance 'unnamed-binding :name nil :value 5))
       #+END_SRC

       #+RESULTS:
       : #

       #+BEGIN_SRC lisp :exports results :results silent
         (ignore-errors
          (remove-method #'print-items:print-items (find-method #'print-items:print-items '(append) (list (find-class 'unnamed-binding)))))
       #+END_SRC

    2. By defining a ~print-items:print-items :around~ method that
       explicitly modifies the complete item list:

       #+BEGIN_SRC lisp :exports both :results value
         (defclass unnamed-binding (binding)
           ())

         (defmethod print-items:print-items :around ((object unnamed-binding))
           (remove :name (call-next-method) :key #'first))

         (princ-to-string (make-instance 'unnamed-binding :name nil :value 5))
       #+END_SRC

       #+RESULTS:
       : #

       #+BEGIN_SRC lisp :exports results :results silent
         (ignore-errors
          (remove-method #'print-items:print-items (find-method #'print-items:print-items '(:around) (list (find-class 'unnamed-binding)))))
       #+END_SRC

*** Formatting Items

    When it is necessary to take full control of item formatting, the
    functions ~utilities.print-items:format-item~ and
    ~utilities.print-items:format-items~ can be used:

    #+BEGIN_SRC lisp :exports both :results value
      (defclass custom-printing-binding (binding)
        ())

      (defmethod print-object ((object custom-printing-binding) stream)
        (print-unreadable-object (object stream :type t :identity t)
          (let ((items (utilities.print-items:effective-print-items object)))
            (format stream "my name is ~/utilities.print-items:format-item/, ~
                            my value is ~/utilities.print-items:format-item/, ~
                            the normal format would be ~
                            |~/utilities.print-items:format-items/|"
                    (find :name items :key #'utilities.print-items::parse-item)
                    (find :value items :key #'utilities.print-items::parse-item)
                    items))))

      (princ-to-string (make-instance 'custom-printing-binding :name "name" :value 5))
    #+END_SRC

    #+RESULTS:
    : #

* Reference

  The =utilities.print-items= system provides the following protocol
  for composable printing:

  * =print-items:print-items OBJECT [generic function]=

    Return a list of items that should appear in the printed
    representation of =OBJECT=.

    Each method should return a list of items of the form

    #+BEGIN_EXAMPLE
      ITEM              ::= (KEY-AND-OPTIONS FORMAT-CONTROL ARGUMENT*)

      KEY-AND-OPTIONS   ::= KEY
                            | (KEY OPTION*)
      KEY               ::= any Lisp object
      OPTION            ::= CONSTRAINT
      CONSTRAINT        ::= ((:before | :after) KEY)

      FORMAT-CONTROL    ::= `nil'
                            | a format control string or a formatter function
      ARGUMENT          ::= any Lisp object
    #+END_EXAMPLE

    When multiple items have =cl:eql= =KEY= s, items appearing closer
    to the beginning of the item list take precedence. This mechanism
    can be used by subclasses to replace print items produced by
    superclasses.

    When =FORMAT-CONTROL= is =nil=, the whole item is ignored. This
    mechanism can be used by subclasses to disable print items
    produced by superclasses.

  * =print-items:print-items-mixin [class]=

    This mixin class adds printing via =print-items= to classes.

    Subclasses can define methods on =print-items:print-items= to
    change or extend the printed representation.

  * =print-items:format-item STREAM ITEM &optional COLON? AT? [function]=

    This utility function prints a single item in the format
    constructed by the =print-items= function to a stream.

  * =print-items:format-items STREAM ITEMS &optional COLON? AT? [function]=

    This utility function prints items in the format constructed by
    the =print-items= function to a stream.

    It is used to implement the =cl:print-object= method for
    =print-items-mixin=.


2 Systems

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


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

2.1 utilities.print-items

A protocol for flexible and composable printing.

Maintainer

Jan Moringen <jmoringe@techfak.uni-bielefeld.de>

Author

Jan Moringen <jmoringe@techfak.uni-bielefeld.de>

License

LGPLv3

Version

0.2.0

Dependency

alexandria (system).

Source

utilities.print-items.asd.

Child Components

3 Modules

Modules are listed depth-first from the system components tree.


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

3.1 utilities.print-items/code

Source

utilities.print-items.asd.

Parent Component

utilities.print-items (system).

Child Components

4 Files

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


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

4.1 Lisp


4.1.1 utilities.print-items/utilities.print-items.asd

Source

utilities.print-items.asd.

Parent Component

utilities.print-items (system).

ASDF Systems

utilities.print-items.


4.1.2 utilities.print-items/code/package.lisp

Source

utilities.print-items.asd.

Parent Component

code (module).

Packages

utilities.print-items.


4.1.3 utilities.print-items/code/util.lisp

Dependency

package.lisp (file).

Source

utilities.print-items.asd.

Parent Component

code (module).

Internals

4.1.4 utilities.print-items/code/protocol.lisp

Dependency

util.lisp (file).

Source

utilities.print-items.asd.

Parent Component

code (module).

Public Interface

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

4.2 Static


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

4.2.1 utilities.print-items/README.org

Source

utilities.print-items.asd.

Parent Component

utilities.print-items (system).


5 Packages

Packages are listed by definition order.


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

5.1 utilities.print-items

Utilities for composable printing.

The interface consists of

* ‘print-items’ [generic function]

Methods extend the printed representation of an object in a composable manner.

* ‘print-items-mixin’ [class]

Can be used to make subclasses the print items mechanism when passed to ‘print-object’.

* ‘format-items’ [function]

Utility function for formatting print items onto a stream.

Source

package.lisp.

Nickname

print-items

Use List
  • alexandria.
  • common-lisp.
Public Interface
Internals

6 Definitions

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


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

6.1 Public Interface


6.1.1 Ordinary functions

Function: format-item (stream item &optional colon? at?)
Package

utilities.print-items.

Source

protocol.lisp.

Function: format-items (stream items &optional colon? at?)

Print ITEMS onto STREAM.

ITEMS is a list of items of the form

(KEY-AND-OPTIONS FORMAT-CONTROL ARGUMENT*)

where

KEY-AND-OPTIONS ::= KEY
| (KEY OPTION*)
KEY ::= any Lisp object
OPTION ::= CONSTRAINT
CONSTRAINT ::= ((:before | :after) KEY)

FORMAT-CONTROL ::= ‘nil’
| a format control string or a formatter function ARGUMENT ::= any Lisp object

Package

utilities.print-items.

Source

protocol.lisp.

Function: format-print-items (stream items &optional colon? at?)

Alias for ‘format-items’.

Package

utilities.print-items.

Source

protocol.lisp.


6.1.2 Generic functions

Generic Function: effective-print-items (object)

Return a list of items like ‘print-items’, but filtered and sorted.

Filtering removes all but the first occurrence of multiple items using the same key.

Sorting arranges the filtered items according to their specified constraints.

Package

utilities.print-items.

Source

protocol.lisp.

Methods
Method: effective-print-items (object)
Generic Function: print-items (object)

Return a list of items that should appear in the printed
representation of OBJECT.

Each method should return a list of items of the form

ITEM ::= (KEY-AND-OPTIONS FORMAT-CONTROL ARGUMENT*)

KEY-AND-OPTIONS ::= KEY
| (KEY OPTION*)
KEY ::= any Lisp object
OPTION ::= CONSTRAINT
CONSTRAINT ::= ((:before | :after) KEY)

FORMAT-CONTROL ::= ‘nil’
| a format control string or a formatter function ARGUMENT ::= any Lisp object

When multiple items have ‘eql’ KEYs, items appearing closer to the beginning of the item list take precedence. This mechanism can be used by subclasses to replace print items produced by superclasses.

When FORMAT-CONTROL is ‘nil’ the whole item is ignored. This mechanism can be used by subclasses to disable print items
produced by superclasses.

Package

utilities.print-items.

Source

protocol.lisp.

Method Combination

append.

Options

:most-specific-first

Methods
Method: print-items append (object)

6.1.3 Standalone methods

Method: print-object ((object print-items-mixin) stream)
Source

protocol.lisp.


6.1.4 Classes

Class: print-items-mixin

This mixin class adds printing via ‘print-items’ to classes.

Package

utilities.print-items.

Source

protocol.lisp.

Direct methods

print-object.


6.2 Internals


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

6.2.1 Macros

Macro: destructure-item ((key &optional enabled? format-control values options) item &body body)
Package

utilities.print-items.

Source

util.lisp.


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

6.2.2 Ordinary functions

Function: item-< (left right)

Return non-nil if the left item should be placed before the right.

Package

utilities.print-items.

Source

util.lisp.

Function: make-node (object)
Package

utilities.print-items.

Source

util.lisp.

Function: maybe-convert-legacy-item (item)
Package

utilities.print-items.

Source

util.lisp.

Reader: node-edges (instance)
Writer: (setf node-edges) (instance)
Package

utilities.print-items.

Source

util.lisp.

Target Slot

edges.

Reader: node-object (instance)
Package

utilities.print-items.

Source

util.lisp.

Target Slot

object.

Reader: node-state (instance)
Writer: (setf node-state) (instance)
Package

utilities.print-items.

Source

util.lisp.

Target Slot

state.

Function: parse-item (item)
Package

utilities.print-items.

Source

util.lisp.

Function: sort-with-partial-order (sequence predicate)
Package

utilities.print-items.

Source

util.lisp.

Function: topological-sort (nodes)
Package

utilities.print-items.

Source

util.lisp.


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

6.2.3 Generic functions

Generic Reader: cycle-error-path (condition)
Package

utilities.print-items.

Methods
Reader Method: cycle-error-path ((condition cycle-error))
Source

util.lisp.

Target Slot

%path.


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

6.2.4 Conditions

Condition: cycle-error
Package

utilities.print-items.

Source

util.lisp.

Direct superclasses

error.

Direct methods

cycle-error-path.

Direct Default Initargs
InitargValue
:path(error missing required initarg for class ~s: ~s (quote cycle-error) path)
Direct slots
Slot: %path
Initargs

:path

Readers

cycle-error-path.

Writers

This slot is read-only.


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

6.2.5 Structures

Structure: node
Package

utilities.print-items.

Source

util.lisp.

Direct superclasses

structure-object.

Direct slots
Slot: object
Readers

node-object.

Writers

This slot is read-only.

Slot: edges
Type

list

Initform

(quote nil)

Readers

node-edges.

Writers

(setf node-edges).

Slot: state
Type

(member :new :in-progress :done)

Initform

:new

Readers

node-state.

Writers

(setf node-state).


Appendix A Indexes


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

A.1 Concepts


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

A.2 Functions

Jump to:   (  
C   D   E   F   G   I   M   N   P   S   T  
Index Entry  Section

(
(setf node-edges): Private ordinary functions
(setf node-state): Private ordinary functions

C
cycle-error-path: Private generic functions
cycle-error-path: Private generic functions

D
destructure-item: Private macros

E
effective-print-items: Public generic functions
effective-print-items: Public generic functions

F
format-item: Public ordinary functions
format-items: Public ordinary functions
format-print-items: Public ordinary functions
Function, (setf node-edges): Private ordinary functions
Function, (setf node-state): Private ordinary functions
Function, format-item: Public ordinary functions
Function, format-items: Public ordinary functions
Function, format-print-items: Public ordinary functions
Function, item-<: Private ordinary functions
Function, make-node: Private ordinary functions
Function, maybe-convert-legacy-item: Private ordinary functions
Function, node-edges: Private ordinary functions
Function, node-object: Private ordinary functions
Function, node-state: Private ordinary functions
Function, parse-item: Private ordinary functions
Function, sort-with-partial-order: Private ordinary functions
Function, topological-sort: Private ordinary functions

G
Generic Function, cycle-error-path: Private generic functions
Generic Function, effective-print-items: Public generic functions
Generic Function, print-items: Public generic functions

I
item-<: Private ordinary functions

M
Macro, destructure-item: Private macros
make-node: Private ordinary functions
maybe-convert-legacy-item: Private ordinary functions
Method, cycle-error-path: Private generic functions
Method, effective-print-items: Public generic functions
Method, print-items: Public generic functions
Method, print-object: Public standalone methods

N
node-edges: Private ordinary functions
node-object: Private ordinary functions
node-state: Private ordinary functions

P
parse-item: Private ordinary functions
print-items: Public generic functions
print-items: Public generic functions
print-object: Public standalone methods

S
sort-with-partial-order: Private ordinary functions

T
topological-sort: Private ordinary functions

Jump to:   (  
C   D   E   F   G   I   M   N   P   S   T  

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

A.4 Data types

Jump to:   C   F   M   N   P   R   S   U  
Index Entry  Section

C
Class, print-items-mixin: Public classes
code: The utilities․print-items/code module
Condition, cycle-error: Private conditions
cycle-error: Private conditions

F
File, package.lisp: The utilities․print-items/code/package․lisp file
File, protocol.lisp: The utilities․print-items/code/protocol․lisp file
File, readme.org: The utilities․print-items/readme․org file
File, util.lisp: The utilities․print-items/code/util․lisp file
File, utilities.print-items.asd: The utilities․print-items/utilities․print-items․asd file

M
Module, code: The utilities․print-items/code module

N
node: Private structures

P
Package, utilities.print-items: The utilities․print-items package
package.lisp: The utilities․print-items/code/package․lisp file
print-items-mixin: Public classes
protocol.lisp: The utilities․print-items/code/protocol․lisp file

R
readme.org: The utilities․print-items/readme․org file

S
Structure, node: Private structures
System, utilities.print-items: The utilities․print-items system

U
util.lisp: The utilities․print-items/code/util․lisp file
utilities.print-items: The utilities․print-items system
utilities.print-items: The utilities․print-items package
utilities.print-items.asd: The utilities․print-items/utilities․print-items․asd file

Jump to:   C   F   M   N   P   R   S   U