(module lambda-doc-slides (lib "run.ss" "slideshow") (require (lib "code.ss" "slideshow")) (define (do-slide-1) (slide/title/center "Basic Scheme Macros for Function Docs" (t "Richard Cleis") (t "ABQ Lisp/Scheme Users Group") (t "Albuquerque, New Mexico") (t "December 16, 2007"))) (define (do-bottom-line) (slide/title/center "A Few dozen pages to describe the following..." (code (lam-w/args args body) (lam-w/expr args body) (lam-w/info info args body)) (code (docs-for function) (list-docs function1 \[function2 ...\])) (page-para "... yet they are implemented in one page") (page-para "using only elementary techniques of Scheme and define-syntax"))) (define (do-macrology) (slide/title/center "Utilized Macro Features" (page-para "S-Expressions are handled, unevaluated, with names") (page-para "(arg . body) handles the lambda form, which is 'implied-begin'") (page-para "Ellipses represent the names of multiple input functions") (page-para "Nameless procedures have temporary names in macroland") (page-para "Syntax-error is used as described in define-syntax-primer.txt") )) (define show-outline (let ([sub-para (lambda l (apply para (* 3/4 client-w) l))]) (make-outline 'what "Means for associating information with lambda expressions" ; (lambda (tag) (sub-para "Intended for high level functions in workspaces")) 'why "High level programming often requires quick reference" (lambda (tag) (sub-para "Digging through source isn't always practical")) 'how "Slight variations of lambda fill a table of expressions" (lambda (tag) (sub-para "A few macros and functions access the expressions")) 'examples "Examples: 3 similar macros" (lambda (tag) (sub-para "May reference functions or expressions")) 'explanation "Lambda implementation is leached for args and body" (lambda (tag) (sub-para "Function reference (not name) provides key")) 'conclusions "Conclusions: Scheme + syntax-language... effective" (lambda (tag) (sub-para "Many solutions can easily be investigated")) ))) (define (do-how:details) (slide/title/center "How to doc lamba expressions" (page-para "Three macros fill doc table; two are just like lambda:") (code (lam-w/args args body) (lam-w/expr args body) (lam-w/info info args body)) (page-para "A function, docs-for, extracts the docs") (code (docs-for function)) (page-para "A macro can be used to associate names to docs") (code (list-docs function1 \[function2 ...\])) (page-para "Docs-for works with any name for a function (including none)") (page-para "List-docs lists the docs with any name for the function"))) (define (do-examples:args) (slide/title/center "Macro that saves expression for the args" (page-para "Often, carefully named args are enough to 'jog your memory'") (code (define interest-a (lam-w/args (principal percent) (* principal 0.01 percent)))) (page-para "To get the docs, use:") (code > (docs-for interest-a) \; produces... (lambda (principal percent))) (page-para "To associate a name:") (code > (list-docs interest-a) \; produces... (interest-a (lambda (principal percent)))) )) (define (do-examples:expr) (slide/title/center "Macro that saves the expression for the entire function" (page-para "High level functions may be short; lam-w/expr can doc them") (code (define interest-e (lam-w/expr (principal percent) (* principal 0.01 percent)))) (code > (docs-for interest-e) \; produces... (lambda (principal percent) (* principal 0.01 percent))))) (define (do-examples:info) (slide/title/center "Macro that saves the expression for anything" (page-para "Sometimes, a string is desired (Any legal expression is ok)" (page-item "Docs-for will evaluate the info expression if it is a procedure") (page-item "Nature is upset, though; lambda now has info, args, and a body") ) (code (define interest-i (lam-w/info "Supply principal & rate as percent" (principal percent) (* principal 0.01 percent)))) (code > (docs-for interest-i) "Supply principal & rate as percent") )) (define (do-examples:info-f) (slide/title/center "Macro that saves the expression for a function" (page-para "A function in the first arg can do anything" (page-item "It evaluates whenever docs-for is used") (page-item "The arg may be a function name (below, it's embedded)") (page-item "GUI's and talking docs are easy to implement") ) (code (define interest-f (lam-w/info (lambda () (display "This could feed a gui") (newline)) (principal percent) (* principal percent)))) (code > (docs-for interest-f) "This could feed a gui") )) (define (do-examples:list-docs) (slide/title/center "List-docs macro associates names with docs" (page-para "A function would need the names and the procedures" (page-item "Scheme extracts a name with 'tick... frightens Schemeaphobics") (page-item "A list of pairings is normally needed, anyway... ergo: this macro")) (code > (list-docs interest-a interest-e interest-i interest-f) ((interest-a (lambda (principal percent))) (interest-e (lambda (principal percent) (* principal 0.01 percent))) (interest-i "Supply principal & rate as percent") (interest-f \#))) )) (define (do-examples:nameless) (slide/title/center "All previous examples listed as nameless procedures:" (code (define list-of-functions (list (lam-w/args (principal percent) (* principal 0.01 percent)) (lam-w/expr (principal percent) (* principal 0.01 percent)) (lam-w/info "Supply principal & rate as percent" (principal percent) (* principal 0.01 percent)) (lam-w/info (lambda () (display "This could feed a gui") (newline)) (principal percent) (* principal 0.01 percent))))))) (define (do-examples:list) (slide/title/center "Docs-for works with the list of nameless procedures" (page-para "The four procedures only appear identical in this REPL") (page-para "All are actually distinct keys to the docs...") (code > list-of-functions (\# \# \# \#)) )) (define (do-examples:map) (slide/title/center "Docs-for naturally maps the nameless list" (code > (map docs-for list-of-functions) This could feed a gui ((lambda (principal percent)) (lambda (principal percent) (* principal 0.01 percent)) "Supply principal & rate as percent" \#)) (page-para "The doc of the last procedure returns void after displaying the text") (page-para "Function synonyms work, too" (page-item "Function names contain a procedure just like an element of a list")) )) (define (do-args&expr) (slide/title/center "Macros copy expressions in lambda and table the docs" (page-para "The temporary f is formed in syntax space" (page-item "f is used for the key and the Macro's final value.")) (code (define-syntax lam-w/args (syntax-rules () ((_ args . body) (let ((f (lambda args . body))) (sort-table! f '(lambda args)) f)) ((_ ...) (syntax-error "Use λ form. Expr for args will be tabled." ))))) (page-para "lam-w/args replaces the sort line with:") (code (sort-table! f '(lambda args . body))) )) (define (do-tabler) (slide/title/center "A simple list and one function for making docs" (page-para "Any 'real' sorter or hash-table could be used" (page-item "yet a textbook list works, and is silly-simple.")) (code (define table (list)) (define sort-table! (lambda f&info ; simplest 'sorter' (set! table (cons f&info table)))) (define (get-info f table) ; lookup for simplest 'sorter' (cond ((null? table) #f) ((equal? f (caar table)) (cadar table)) (else (get-info f (cdr table)))))) )) (define (do-docs-for) (slide/title/center "docs-for evaluates a procedure if it gets one" (page-para "docs-for is defined with lam-w/args" (page-item "(docs-for docs-for) returns the expression for its args") (page-item "Programming has no soul if such things are not kewl")) (code (define docs-for (lam-w/args (f-as-key) (do-info (get-info f-as-key table)))) (define do-info (lambda (info) ; info handlers go in here (cond (info (cond ((procedure? info) (info)) (else info))) (else 'not-in-table))))) )) (define (do-list-docs) (slide/title/center "The list-docs macro lists a name with the docs" (page-para "To be used for making help tables in GUIs, for example" (page-item "The macro allows 'ticking' the procedure name, and") (page-item "forming the list with ellipses")) (code (define-syntax list-docs (syntax-rules () ((_ f ...) (list (list 'f (get-info f table)) ...)) ((_ ...) (syntax-error "Use (list-docs f [...])"))))))) (define (do-info) (slide/title/center "lam-w/info expects an expression, info, before args" (page-para "Docs-for will evaluate info if a function, return info otherwise") (code (define-syntax lam-w/info (syntax-rules () ((_ info args . body) (let ((f (lambda args . body))) (sort-table! f info) ; table info expression f)) ((_ ...) (syntax-error "Use λ form, but put info before args."))))) )) (define (do-syntax-error) (slide/title/center "Macro syntax-error from define-syntax-primer.txt" (page-para "Causes REPL to provide information about the macro" (page-item "Designed to work with recursive macros") (page-item "Designed to fail so that caller's text is returned") (page-item "Programming has no soul if... oh, never mind")) (code (define-syntax syntax-error (syntax-rules () ((syntax-error) (syntax-error "Bad use of syntax error!"))))) )) (define (do-conclusions) (slide/title/center "Conclusions other than: this solution is practical" (page-para "Macros permit matching multiple patterns and recursion, but in this case it is easier to read, debug, and use a macro for each form") (page-para "Basing these macros on lambda (instead of define) is more flexible" (page-item "E.g. when using synonyms and lists of unnamed functions")) (page-para "Possible non-portable improvements" (page-item "Use hash-tables or sorting functions to table information") (page-item "Contain code in a Scheme Module (like this implementation)") (page-item "Use GUI to display and manipulate the information") ) (page-para "The reasons for define-syntax are learned by doing, not reading") )) (define do-all #t) (cond (do-all (do-slide-1) (do-bottom-line) (do-macrology) (show-outline 'none) (show-outline 'what) (show-outline 'why) (show-outline 'how) (show-outline 'examples) (show-outline 'explanation) (show-outline 'conclusions) (show-outline 'how) (do-how:details) (show-outline 'examples) (do-examples:args) (do-examples:expr) (do-examples:info) (do-examples:info-f) (do-examples:list-docs) (do-examples:nameless) (do-examples:list) (do-examples:map) (show-outline 'explanation) (do-args&expr) (do-tabler) (do-docs-for) (do-list-docs) (do-info) (do-syntax-error) (show-outline 'conclusions) (do-conclusions) ) (else (show-outline 'examples) (do-examples:args) (do-examples:expr) (do-examples:info) (do-examples:info-f) (do-examples:list-docs) (do-examples:nameless) (do-examples:list) (do-examples:map) )))