Sdraw: Cons-Cell Diagrams with Pict
(require sdraw) | package: sdraw |
Cons-cell diagrams (also called box-and-pointer diagrams) are often used to visually depict pairs and lists, typically in an educational context. For example,a cons-cell diagram for the list '(1 (2 3) 4) can be seen below:
Sdraw can be used to automatically create these diagrams using Pict. Inspiration for sdraw comes from the SDRAW program included with David S. Touretzky’s Common Lisp: A Gentle Introduction to Symbolic Computation. Like Touretzky’s program, circular lists and other graph-like structures are supported.
1 Usage
There is only one function provided by sdraw:
procedure
(sdraw obj [ #:cell-border-color cell-border-color #:cell-inside-color cell-inside-color #:arrow-color arrow-color #:arrow-thickness arrow-thickness #:arrow-head-size arrow-head-size #:arrow-point-size arrow-point-size #:object-padding object-padding #:cell-inside-size cell-inside-size #:cell-inside-radius cell-inside-radius #:cell-border-radius cell-border-radius #:cell-border-width cell-border-width #:vertical-spacing vertical-spacing #:horizontal-spacing horizontal-spacing #:etc-pict etc-pict #:null-style null-style #:null-thickness null-thickness #:max-depth max-depth #:max-width max-width #:reference-label reference-label]) → pict? obj : any/c cell-border-color : color/c = "Black" cell-inside-color : color/c = "White" arrow-color : color/c = "Black" arrow-thickness : real? = 2.5 arrow-head-size : real? = 7.5 arrow-point-size : real? = 7.5 object-padding : real? = 1 cell-inside-size : real? = 15 cell-inside-radius : real? = 1.5 cell-border-radius : real? = 1.5 cell-border-width : real? = 2 vertical-spacing : real? = 25 horizontal-spacing : real? = 40 etc-pict : pict-convertible? = (text "etc.")
null-style : (or/c pict-convertible? '/ '|\| 'x) = (typeset-code #'()) null-thickness : real? = 2.5 max-depth : (or/c +inf.0 natural-number/c) = +inf.0 max-width : (or/c +inf.0 natural-number/c) = +inf.0
reference-label : (-> string? pict-convertible?) = default-reference-label
Pairs are drawn as a box, with arrows going down and right for the car and cdr respectively. If a pict-convertible? is given, it will be drawn directly. Otherwise, it will be converted to a pict? using typeset-code.
Various optional keyword arguments can be given to sdraw to customize the appearance:
Limiting size: For large objects, you may wish to limit the amount of pairs drawn. Using max-depth and max-width, you can specify how far deep or out will be drawn before pairs are replaced by etc-pict.
Example:Null style: By default, null will be represented by an arrow to (). However, other styles are common practice. For example, in SICP, null is represented using a slash thru the containing pair.
null-style may specify an alternative pict-convertible? to show. For example:
Examples:> (sdraw '(nconc result) #:null-style (text "NIL")) > (sdraw '(()) #:null-style (typeset-code #'null)) Alternatively, null-style may specify one of three in-cell styles:
Examples:Finally, use the null-thickness option to adjust the width of the lines used to draw in-cell styles (the option has no effect when null-style is pict-convertible?):
Example:> (sdraw '(1 2) #:null-style '/ #:null-thickness 0.5) Spacing: Use the horizontal-spacing and vertical-spacing options.
Example:> (sdraw '(a b) #:horizontal-spacing 100 #:vertical-spacing 10) To add space around the text and any other drawn pictures, use the object-padding option:Examples:Cell style: Use the cell-border-color, cell-inside-color, cell-inside-size, cell-inside-radius, cell-border-radius, and cell-border-width options.
Example:> (sdraw '(a b) #:cell-inside-color "Green" #:cell-border-color "Purple" #:cell-inside-size 20 #:cell-inside-radius 10 #:cell-border-radius 10 #:cell-border-width 3 #:null-style '/) Arrow style: arrow-color, arrow-thickness, arrow-head-size, and arrow-point-size can be used to adjust the size of the arrows.
Example:> (sdraw '(+ (* 2 3) 4) #:arrow-color "Purple" #:arrow-thickness 1 #:arrow-head-size 5 #:arrow-point-size 10) Reference labels style: Customization of labels for circular and graph-like structures can be done by passing a function which takes a string? and produces a pict-convertible? for reference-label. By default, a simple black label with white text is used:
Examples:> (require racket) > (sdraw (with-input-from-string "#0=(#0# #1=(#0# . #1#) #1#)" read)) > (sdraw (with-input-from-string "#0=(#0# #1=(#0# . #1#) #1#)" read) #:reference-label text)