Hello, friendly and knowledgeable fellow Lispers. I'm trying to write a little library to provide charting capabilities over Vecto. For my first task, I'm trying to mimic Vecto's method of drawing images but at a slightly higher level (for the user). So I've provided a WITH-PIE-CHART macro that the user would utilize like this:
Thanks for any hints or ideas.
(taylor-chart:with-pie-chart ("test.png" 256)
(add-slice 25)
(add-slice 50)
(add-slice 75)
(add-slice 100))
As you can see, all of this is inside a package TAYLOR-CHART. My current definition of WITH-PIE-CHART has some flaws:(defpackage :taylor-chart
(:use :common-lisp :vecto)
(:export :with-pie-chart))
(in-package :taylor-chart)
(defmacro with-pie-chart ((file radius) &rest body)
`(let ((slice-pieces nil)
(slice-spacing 0))
(flet ((add-slice (value &optional caption color)
(setf slice-pieces (cons value slice-pieces))))
(with-canvas (:width ,radius :height ,radius)
,@body
(format t "~a~%" slice-pieces)
(translate (/ ,radius 2) (/ ,radius 2))
(setf slice-pieces (nreverse slice-pieces))
(let ((idx 0) (sum (reduce #'+ slice-pieces))
(len (length slice-pieces)))
(reduce (lambda (x y)
(let ((z (* (/ y sum) 2 pi)))
(incf idx)
(format t "Drawing arc: ~a ~a~%" x (+ x z))
(set-rgb-fill (/ idx len) (/ idx len) (/ idx len))
(move-to 0 0)
(arc 0 0 128 x (+ x z))
(fill-and-stroke)
(+ x z))) slice-pieces :initial-value 0)
(save-png ,file))))))
Namely, the bindings created by LET and FLET end up in the TAYLOR-CHART package, where they cannot be found by the user. The expansion is:(LET ((TAYLOR-CHART::SLICE-PIECES NIL) (TAYLOR-CHART::SLICE-SPACING 0))
(FLET ((TAYLOR-CHART::ADD-SLICE
(TAYLOR-CHART::VALUE
&OPTIONAL TAYLOR-CHART::CAPTION TAYLOR-CHART::COLOR)
(SETF TAYLOR-CHART::SLICE-PIECES
(CONS TAYLOR-CHART::VALUE TAYLOR-CHART::SLICE-PIECES))))
(VECTO:WITH-CANVAS (:WIDTH 256 :HEIGHT 256) (ADD-SLICE 25) (ADD-SLICE 50)
(ADD-SLICE 75) (ADD-SLICE 100)
(FORMAT T "~a~%" TAYLOR-CHART::SLICE-PIECES)
(VECTO:TRANSLATE (/ 256 2) (/ 256 2))
(SETF TAYLOR-CHART::SLICE-PIECES
(NREVERSE TAYLOR-CHART::SLICE-PIECES))
(LET ((TAYLOR-CHART::IDX 0)
(TAYLOR-CHART::SUM
(REDUCE #'+ TAYLOR-CHART::SLICE-PIECES))
(TAYLOR-CHART::LEN
(LENGTH TAYLOR-CHART::SLICE-PIECES)))
(REDUCE
(LAMBDA (TAYLOR-CHART::X TAYLOR-CHART::Y)
(LET ((TAYLOR-CHART::Z
(* (/ TAYLOR-CHART::Y TAYLOR-CHART::SUM) 2
PI)))
(INCF TAYLOR-CHART::IDX)
(FORMAT T "Drawing arc: ~a ~a~%" TAYLOR-CHART::X
(+ TAYLOR-CHART::X TAYLOR-CHART::Z))
(VECTO:SET-RGB-FILL
(/ TAYLOR-CHART::IDX TAYLOR-CHART::LEN)
(/ TAYLOR-CHART::IDX TAYLOR-CHART::LEN)
(/ TAYLOR-CHART::IDX TAYLOR-CHART::LEN))
(VECTO:MOVE-TO 0 0)
(VECTO:ARC 0 0 128 TAYLOR-CHART::X
(+ TAYLOR-CHART::X TAYLOR-CHART::Z))
(VECTO:FILL-AND-STROKE)
(+ TAYLOR-CHART::X TAYLOR-CHART::Z)))
TAYLOR-CHART::SLICE-PIECES :INITIAL-VALUE 0)
(VECTO:SAVE-PNG "test.png")))))
How can I avoid or work around this? When I move everything into the same package (for example by defining the macro in the CL-USER package, explicitly marking the Vecto functions, and trying my example usage from there), it works as expected.Thanks for any hints or ideas.
"I have never let my schooling interfere with my education." -- Mark Twain