Next: Introduction, Previous: (dir), Up: (dir) [Contents][Index]
This is the utilities.print-items Reference Manual, version 0.2.0, generated automatically by Declt version 3.0 "Montgomery Scott" on Tue Dec 22 15:25:34 2020 GMT+0.
• Introduction | What utilities.print-items is all about | |
• Systems | The systems documentation | |
• Modules | The modules documentation | |
• Files | The files documentation | |
• Packages | The packages documentation | |
• Definitions | The symbols documentation | |
• Indexes | Concepts, functions, variables and data types |
#+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 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 CLOS' flexibility 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 method 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 ,(name object) "~S"))) (defclass value-mixin () ((%value :initarg :value :reader value))) (defmethod print-items:print-items append ((object value-mixin)) `((:value ,(value object) "= ~S"))) (defclass binding (name-mixin value-mixin) ()) (defmethod print-object ((object binding) stream) (print-unreadable-object (object stream :type t :identity t) (print-items:format-print-items stream (print-items: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 ,(value object) " = ~S" ((:AFTER :NAME))))) (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 It is sometimes necessary to modify the print items produced by 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 nil "«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 * 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 (KEY VALUE [FORMAT [(CONSTRAINT*)]] #+END_EXAMPLE where #+BEGIN_EXAMPLE KEY ::= any Lisp object VALUE ::= any Lisp object FORMAT ::= nil or a format string (Default is \"~A\") CONSTRAINT ::= (:before | :after) KEY #+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= 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-print-items STREAM ITEMS &optional COLON? AT? [function]= This utility function prints items in the format constructed by the =print-items= functions to a stream. It is used to implement the =cl:print-object= method for =print-items-mixin=.
Next: Modules, Previous: Introduction, Up: Top [Contents][Index]
The main system appears first, followed by any subsystem dependency.
• The utilities.print-items system |
Jan Moringen <jmoringe@techfak.uni-bielefeld.de>
Jan Moringen <jmoringe@techfak.uni-bielefeld.de>
LLGPLv3
A protocol for flexible and composable printing.
0.2.0
alexandria
utilities.print-items.asd (file)
Modules are listed depth-first from the system components tree.
• The utilities.print-items/src module |
utilities.print-items (system)
src/
Files are sorted by type and then listed depth-first from the systems components trees.
• Lisp files | ||
• Static files |
Next: Static files, Previous: Files, Up: Files [Contents][Index]
• The utilities.print-items.asd file | ||
• The utilities.print-items/src/package.lisp file | ||
• The utilities.print-items/src/util.lisp file | ||
• The utilities.print-items/src/protocol.lisp file |
Next: The utilities․print-items/src/package․lisp file, Previous: Lisp files, Up: Lisp files [Contents][Index]
utilities.print-items.asd
utilities.print-items (system)
Next: The utilities․print-items/src/util․lisp file, Previous: The utilities․print-items․asd file, Up: Lisp files [Contents][Index]
src (module)
src/package.lisp
Next: The utilities․print-items/src/protocol․lisp file, Previous: The utilities․print-items/src/package․lisp file, Up: Lisp files [Contents][Index]
package.lisp (file)
src (module)
src/util.lisp
Previous: The utilities․print-items/src/util․lisp file, Up: Lisp files [Contents][Index]
util.lisp (file)
src (module)
src/protocol.lisp
Previous: Lisp files, Up: Files [Contents][Index]
• The utilities.print-items/readme.org file |
Previous: Static files, Up: Static files [Contents][Index]
utilities.print-items (system)
README.org
Next: Definitions, Previous: Files, Up: Top [Contents][Index]
Packages are listed by definition order.
• The utilities.print-items package |
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-print-items’ [function]
Utility function for formatting print items onto a stream.
package.lisp (file)
print-items
Definitions are sorted by export status, category, package, and then by lexicographic order.
• Exported definitions | ||
• Internal definitions |
Next: Internal definitions, Previous: Definitions, Up: Definitions [Contents][Index]
• Exported functions | ||
• Exported generic functions | ||
• Exported classes |
Next: Exported generic functions, Previous: Exported definitions, Up: Exported definitions [Contents][Index]
Print ITEMS onto STREAM.
ITEMS is a list of items of the form
(KEY VALUE [FORMAT [(CONSTRAINT*)]]
where
KEY ::= any Lisp object
VALUE ::= any Lisp object
FORMAT ::= ‘nil’ or a format string (Default is "~A")
CONSTRAINT ::= (:before | :after) KEY
protocol.lisp (file)
Next: Exported classes, Previous: Exported functions, Up: Exported definitions [Contents][Index]
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
(KEY VALUE [FORMAT [(CONSTRAINT*)]]
where
KEY ::= any Lisp object
VALUE ::= any Lisp object
FORMAT ::= ‘nil’ or a format string (Default is "~A")
CONSTRAINT ::= (:before | :after) KEY
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 is ‘nil’ the whole item is ignored. This mechanism can be used by subclasses to disable print items produced by superclasses.
protocol.lisp (file)
append (short method combination)
Options: :most-specific-first
Previous: Exported generic functions, Up: Exported definitions [Contents][Index]
This mixin class adds printing via ‘print-items’ to classes.
protocol.lisp (file)
standard-object (class)
print-object (method)
Previous: Exported definitions, Up: Definitions [Contents][Index]
• Internal functions | ||
• Internal generic functions | ||
• Internal conditions | ||
• Internal structures |
Next: Internal generic functions, Previous: Internal definitions, Up: Internal definitions [Contents][Index]
Return non-nil if the left item should be placed before the right.
util.lisp (file)
util.lisp (file)
util.lisp (file)
util.lisp (file)
util.lisp (file)
util.lisp (file)
util.lisp (file)
Next: Internal conditions, Previous: Internal functions, Up: Internal definitions [Contents][Index]
util.lisp (file)
Next: Internal structures, Previous: Internal generic functions, Up: Internal definitions [Contents][Index]
util.lisp (file)
error (condition)
cycle-error-path (method)
:path
cycle-error-path (generic function)
Initarg | Value |
---|---|
:path | (error "missing required initarg for class ~s: ~s" (quote utilities.print-items::cycle-error) :path) |
Previous: Internal conditions, Up: Internal definitions [Contents][Index]
util.lisp (file)
structure-object (structure)
node-object (function)
(setf node-object) (function)
list
(quote nil)
node-edges (function)
(setf node-edges) (function)
(member :new :in-progress :done)
:new
node-state (function)
(setf node-state) (function)
Previous: Definitions, Up: Top [Contents][Index]
• Concept index | ||
• Function index | ||
• Variable index | ||
• Data type index |
Next: Function index, Previous: Indexes, Up: Indexes [Contents][Index]
Jump to: | F L M S U |
---|
Jump to: | F L M S U |
---|
Next: Variable index, Previous: Concept index, Up: Indexes [Contents][Index]
Jump to: | (
C F G I M N P S T |
---|
Jump to: | (
C F G I M N P S T |
---|
Next: Data type index, Previous: Function index, Up: Indexes [Contents][Index]
Jump to: | %
E O S |
---|
Jump to: | %
E O S |
---|
Previous: Variable index, Up: Indexes [Contents][Index]
Jump to: | C N P S U |
---|
Jump to: | C N P S U |
---|