--- Begin Message ---
Subject: |
Possible bug? |
Date: |
Wed, 12 Feb 2014 00:51:29 +0000 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.2.0 |
#|
This file is an extract of a documentation and code assembly process
which works from a list of elements and attributes. Perhaps I'm
being particularly stupid but I can't see why the function
emit-groff-bug? does not work as expected.
Version is 2.09 GCC is 4.7.3 on 64 bit Ubuntu self compiled.
BTW, thanks to all the developers for a wonderful program. I am
greatly enjoying programming in Guile.
|#
(define-syntax say
(syntax-rules ()
((say format-string ...)
(format #t format-string ...))
((say format-string)
(format #t format-string))))
(define-syntax emit
(syntax-rules ()
((emit a-string)
(say (string-append a-string "\n")))
((emit a-string ...)
(say (string-append (format #f a-string ...) "\n")))))
(define canvas-description
"A canvas object specifies the two dimensional area on which graphics
objects are painted.
The function `canvas' requires at least one parameter, the name by
which the canvas will be known. If there is already a canvas by that
name in the canvas-table then it will be used as the current
canvas. If not then a new canvas will be created using the default
values unless overridden by keyword value pairs passed to the
function.")
(define thoth-canvas
`((#:object-name . canvas)
(#:description . ,canvas-description)
(#:attributes
(viewbox none "Creates user coordinate space")
(background none "Creates a background rectangle")
(transform none "Transformation object"))))
(define (process-attributes-for-groff lst)
(for-each
(lambda (element)
(emit ".attribute ~a ~a" (list-ref element 0)
(list-ref element 1))
(emit ".start-hint")
(emit "~a" (list-ref element 2))
(emit ".end-hint"))
lst))
(define (emit-groff lst)
(for-each
(lambda (element)
(cond ((and (pair? element)
(eq? #:object-name (car element)))
(emit ".object-name ~a" (cdr element)))
((and (pair? element)
(eq? #:description (car element)))
(emit ".start-description")
(emit "~a" (cdr element))
(emit ".end-description"))
((and (list? element)
(eq? #:attributes (car element)))
(process-attributes-for-groff (cdr element)))
(else
(emit "emit-groff | unknown list type")
(throw 'snafu))))
lst))
(define (emit-groff-bug? lst)
(for-each
(lambda (element)
(cond ((pair? element)
(cond ((eq? #:object-name (car element))
(emit ".object-name ~a" (cdr element)))
((eq? #:description (car element))
(emit ".start-description")
(emit "~a" (cdr element))
(emit ".end-description"))))
((list? element)
(cond ((eq? #:attributes (car element)))
(process-attributes-for-groff (cdr element)))
(else
(emit "emit-groff | unknown list type")
(throw 'snafu)))))
lst))
(emit "------------- working")
(emit-groff thoth-canvas)
(emit "------------- not working")
(emit-groff-bug? thoth-canvas)
--- End Message ---
--- Begin Message ---
Subject: |
Re: bug#16726: Possible bug? |
Date: |
Tue, 11 Feb 2014 22:40:32 -0500 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) |
tags 16726 notabug
thanks
Hi,
Nigel Warner <address@hidden> writes:
> This file is an extract of a documentation and code assembly process
> which works from a list of elements and attributes. Perhaps I'm
> being particularly stupid but I can't see why the function
> emit-groff-bug? does not work as expected.
In the future, please show us what output the program produced,
and what output you expected.
There are several mistakes in your program.
> (define-syntax say
> (syntax-rules ()
> ((say format-string ...)
> (format #t format-string ...))
> ((say format-string)
> (format #t format-string))))
The second rule will never be used, because the first rule covers that
case. In macros, "x ..." matches zero or more items.
> (define-syntax emit
> (syntax-rules ()
> ((emit a-string)
> (say (string-append a-string "\n")))
> ((emit a-string ...)
> (say (string-append (format #f a-string ...) "\n")))))
This is a bad idea, because you are conflating the format string with
the strings you want to output. If the string you want to output
includes "~", then it will misbehave. Did you notice the compiler
warnings about non-literal format strings?
> (define (process-attributes-for-groff lst)
> (for-each
> (lambda (element)
> (emit ".attribute ~a ~a" (list-ref element 0)
> (list-ref element 1))
> (emit ".start-hint")
> (emit "~a" (list-ref element 2))
> (emit ".end-hint"))
> lst))
I suggest that you use the (ice-9 match) module to destructure 'element'
into its components. The code will look a lot nicer, and it will also
be more efficient.
> (define (emit-groff lst)
> (for-each
> (lambda (element)
> (cond ((and (pair? element)
> (eq? #:object-name (car element)))
> (emit ".object-name ~a" (cdr element)))
> ((and (pair? element)
> (eq? #:description (car element)))
> (emit ".start-description")
> (emit "~a" (cdr element))
> (emit ".end-description"))
> ((and (list? element)
> (eq? #:attributes (car element)))
> (process-attributes-for-groff (cdr element)))
> (else
> (emit "emit-groff | unknown list type")
> (throw 'snafu))))
> lst))
>
> (define (emit-groff-bug? lst)
> (for-each
> (lambda (element)
> (cond ((pair? element)
> (cond ((eq? #:object-name (car element))
> (emit ".object-name ~a" (cdr element)))
> ((eq? #:description (car element))
> (emit ".start-description")
> (emit "~a" (cdr element))
> (emit ".end-description"))))
> ((list? element)
> (cond ((eq? #:attributes (car element)))
> (process-attributes-for-groff (cdr element)))
> (else
> (emit "emit-groff | unknown list type")
> (throw 'snafu)))))
> lst))
There are several mistakes in this procedure:
* Every list is also a pair, so the (list? element) case is never taken.
The (pair? element) case is taken for the #:attributes, and then no
matching case is found in the inner 'cond' there.
There are two parenthesis errors:
* You have the (process-attributes-for-groff (cdr element)) in a
position where its treated as a clause of the inner 'cond', instead of
as an expression within the (eq? #:attributes (car element)) case.
* You've put the 'else' within the "(list? element)" case, instead of as
its own clause. Did you see the compiler warning about "possibly
unbound variable `else'"?
Mark
--- End Message ---