Author Topic: So you're writing this large lisp application ...  (Read 6687 times)

0 Members and 1 Guest are viewing this topic.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
So you're writing this large lisp application ...
« on: October 08, 2005, 08:14:44 AM »
... and it just isn't functioning the way you want.

So ... to debug it you (1) dump variables (2) put in breakpoints .

What else do you do?
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: So you're writing this large lisp application ...
« Reply #1 on: October 08, 2005, 08:23:24 AM »
>>>>  the way you want.


errors or slow or inconsistant output ??

but yes, essentially dumps and breakpoints. :-(
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Mark

  • Custom Title
  • Seagull
  • Posts: 28762
Re: So you're writing this large lisp application ...
« Reply #2 on: October 08, 2005, 08:32:47 AM »
I sometimes use "(alert (princ var))".

Do you consider that ^ a break point?
TheSwamp.org  (serving the CAD community since 2003)

Peter Jamtgaard

  • Guest
Re: So you're writing this large lisp application ...
« Reply #3 on: October 08, 2005, 08:56:28 AM »
Break the application up into smaller subroutines and functions.
Test each function for desired results.
Spagetti code is functional but hard to debug.
Structured programming is easier to debug, and much of the code becomes reusable.

Like create a library (toolbox.lsp) of useful functions that you use all the time.
Then load the toolbox in every drawing or have the individual routine load the library, or use autoload.

If a routine is used in multiple other routines, move it to your toolbox and take it out of your individual routines.

This keeps the code easier to upgrade and also keeps similar routines

Peter

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: So you're writing this large lisp application ...
« Reply #4 on: October 08, 2005, 09:05:56 AM »
As noted I've found that most folks debug the same way, at least by observing coders at my primary client's office. What's interesting is that as often as this exercise is performed many folks don't have dedicated functions for this important task, as few as they need to be.

So yes -- I too put in dumps and breakpoints.

In it's distilled form I have two simple functions, one called (Dump x) and the other called (Wait). Ok, there's a third called (DumpAndWait x) which is self explainatory and a convenience function 'cause I be lazy.

(Dump x) takes a sole parameter and spews formatted information about the argument -- and here's an important trait -- it then returns the argument as received, in other words it does a pass thru. If the argument passed is a quoted symbol it prints the name and then the data it hosts, otherwise just the data. Example (Dump 'x) versus (Dump x). This will allow me to do things like (setq myPi (Dump pi)), spewing info about the symbol pi, but returning it so it assigned via the setq statement to variable myPi.

(Wait) does nothing but halt program execution until the user presses [Enter].

So ... let's say I define (Dump x), (Wait) and (DumpAndWait x) in a library called debug.lsp.

A contrived little proggy:

Code: [Select]
(defun c:TEST  ( / a b c d e )

    (princ "Begin TEST ...\n\n")

    (setq
        a  1
        b  "2"
        c  ((lambda (x) (repeat 8 (setq x (append x x)))) '(1 2 3))
        d  (ssget "x")
    )

    (dump 'a)

    (dump 'b)
   
    (dump 'c)

    (dump 'd)
   
    (cond
        (   (eq 'pickset (type d))
            (dump (setq e (ssname d 0)))
            (dump (vlax-ename->vla-object e))
        )   
    )

    (princ "End TEST ...\n\n")

    (princ)

)

Might spew ...

Code: [Select]
Begin TEST ...

;================================ Dump 1.0 =================================
;
; Atom Name: A
; Atom Type: INT
;
;===========================================================================
;
; 1
;
;===========================================================================


;================================ Dump 1.0 =================================
;
; Atom Name: B
; Atom Type: STR
;
;===========================================================================
;
; StrLen = 1
;
; "2"
;
;===========================================================================


;================================ Dump 1.0 =================================
;
; Atom Name: C
; Atom Type: LIST
;
;===========================================================================
;
; Length = 768
;
; (1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
; 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1
;  2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1
; 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2
;  3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2
; 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
;  1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
; 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1
;  2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1
; 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2
;  3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2
; 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
;  1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
; 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1
;  2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1
; 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2
;  3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2
; 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
;  1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
; 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1
;  2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1
; 2 3)
;
;===========================================================================


;================================ Dump 1.0 =================================
;
; Atom Name: D
; Atom Type: PICKSET
;
;===========================================================================
;
; SSLength = 1
;
; <Selection set: 21>
;
;===========================================================================


;================================ Dump 1.0 =================================
;
; Atom Type: ENAME
;
;===========================================================================
;
; (
;   (-1 . <Entity name: 7ef70f68>)
;   (0 . "CIRCLE")
;   (330 . <Entity name: 7ef70cf8>)
;   (5 . "A5")
;   (100 . "AcDbEntity")
;   (67 . 0)
;   (410 . "Model")
;   (8 . "0")
;   (100 . "AcDbCircle")
;   (10 33.5609 4.2347 0.0)
;   (40 . 1.30078)
;   (210 0.0 0.0 1.0)
; )
;
;===========================================================================


;================================ Dump 1.0 =================================
;
; Atom Type: VLA-OBJECT
;
;===========================================================================
;
; IAcadCircle: AutoCAD Circle Interface
; Property values:
;   Application (RO) = #<VLA-OBJECT IAcadApplication 00c2eb8c>
;   Area = 5.31566
;   Center = (33.5609 4.2347 0.0)
;   Circumference = 8.17304
;   Diameter = 2.60156
;   Document (RO) = #<VLA-OBJECT IAcadDocument 0cf37924>
;   Handle (RO) = "A5"
;   HasExtensionDictionary (RO) = 0
;   Hyperlinks (RO) = #<VLA-OBJECT IAcadHyperlinks 0e4c0574>
;   Layer = "0"
;   Linetype = "ByLayer"
;   LinetypeScale = 1.0
;   Lineweight = -1
;   Normal = (0.0 0.0 1.0)
;   ObjectID (RO) = 2130120552
;   ObjectName (RO) = "AcDbCircle"
;   OwnerID (RO) = 2130119928
;   PlotStyleName = "ByLayer"
;   Radius = 1.30078
;   Thickness = 0.0
;   TrueColor = #<VLA-OBJECT IAcadAcCmColor 0e4c0cc0>
;   Visible = -1
; Methods supported:
;   ArrayPolar (3)
;   ArrayRectangular (6)
;   Copy ()
;   Delete ()
;   GetBoundingBox (2)
;   GetExtensionDictionary ()
;   GetXData (3)
;   Highlight (1)
;   IntersectWith (2)
;   Mirror (2)
;   Mirror3D (3)
;   Move (2)
;   Offset (1)
;   Rotate (2)
;   Rotate3D (3)
;   ScaleEntity (2)
;   SetXData (2)
;   TransformBy (1)
;   Update ()
;
;===========================================================================

End TEST ...

When I'm done debuggging the application I may decide to keep the debugging tools in place, but define (Dump x), (Wait) and (DumpAndWait x) locally so they have the same signature but do nothing --

Code: [Select]
(defun c:TEST ( / Dump Wait DumpAndWait  a b c d e )

    (defun Dump (x) x)
    (defun Wait ( ) (princ))
    (defun DumpAndWait (x) x)

    (princ "Begin TEST ...\n\n")

    (setq
        a  1
        b  "2"
        c  ((lambda (x) (repeat 8 (setq x (append x x)))) '(1 2 3))
        d  (ssget "x")
    )

    (dump 'a)

    (dump 'b)

    (dump 'c)

    (dump 'd)

    (cond
        (   (eq 'pickset (type d))
            (dump (setq e (ssname d 0)))
            (dump (vlax-ename->vla-object e))
        )
    )

    (princ "End TEST ...\n\n")

    (princ)

)

A run will now output this --

Code: [Select]
Begin TEST ...

End TEST ...

So friends ... how might I improve upon this debuggin technique?
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: So you're writing this large lisp application ...
« Reply #5 on: October 08, 2005, 09:21:47 AM »
errors or slow or inconsistant output ??

Rhetorical question? Both unless that's design/desired behavior?

but yes, essentially dumps and breakpoints. :-(

Why so sad?
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: So you're writing this large lisp application ...
« Reply #6 on: October 08, 2005, 09:23:49 AM »
I sometimes use "(alert (princ var))".

Do you consider that ^ a break point?

I do, it's a dump and a breakpoint.

:)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: So you're writing this large lisp application ...
« Reply #7 on: October 08, 2005, 09:25:29 AM »
Break the application up into smaller subroutines and functions ... <other good stuff snipped to save the binary trees>

Fully agree with your post Peter.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: So you're writing this large lisp application ...
« Reply #8 on: October 08, 2005, 09:27:38 AM »
:-( 'cause that the only 2 real options I can offer are the ones you mention.

Looks like I do the quoted var list similar to the method you mentioned. I also use dotted pair lists, but thats just dumps too I 'spose.

yeah, rhetorical really .. just wondered if you had a particular issue.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

JohnK

  • Administrator
  • Seagull
  • Posts: 10648
Re: So you're writing this large lisp application ...
« Reply #9 on: October 08, 2005, 09:41:17 AM »
wow?! Some hard thinking is doing in my head early morning this  ...*snap*

I think you broke him!?  Dont worry folks, I'll get the coffee.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: So you're writing this large lisp application ...
« Reply #10 on: October 08, 2005, 09:44:15 AM »
:-( 'cause that the only 2 real options I can offer are the ones you mention.

Looks like I do the quoted var list similar to the method you mentioned. I also use dotted pair lists, but thats just dumps too I 'spose.

yeah, rhetorical really .. just wondered if you had a particular issue.

I don't do anything special with dotted pairs, it's just a list as far as the dump function is concerned --

Code: [Select]
(dump '((1 . "A string of some kind.")(70 . 42)))

;================================ Dump 1.0 =================================
;
; Atom Type: LIST
;
;===========================================================================
;
; Length = 2
;
; ((1 . "A string of some kind.") (70 . 42))
;
;===========================================================================

Unless the argument passed is an ename, then it attempts to format the entity data accordingly:

Code: [Select]
(dump
    (   (lambda (ss)
            (if (eq 'pickset (type ss))           
                (ssname ss 0)
               'Nada
            )
        )
        (ssget "x")
    )   
)

;================================ Dump 1.0 =================================
;
; Atom Type: ENAME
;
;===========================================================================
;
; (
;   (-1 . <Entity name: 7ef70f68>)
;   (0 . "CIRCLE")
;   (330 . <Entity name: 7ef70cf8>)
;   (5 . "A5")
;   (100 . "AcDbEntity")
;   (67 . 0)
;   (410 . "Model")
;   (8 . "0")
;   (100 . "AcDbCircle")
;   (10 33.5609 4.2347 0.0)
;   (40 . 1.30078)
;   (210 0.0 0.0 1.0)
; )
;
;===========================================================================
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

JohnK

  • Administrator
  • Seagull
  • Posts: 10648
Re: So you're writing this large lisp application ...
« Reply #11 on: October 08, 2005, 09:49:19 AM »
*huff* *puff* *sputter* *BANG* *chug, chug...*

What if you pass a procedure as a whole and eval each "line". If you pass a giant list, you would have to start with the inner most list and eval it, pause and eval the next level up. And so on.   ...Feesable? prolly. Level of diff. challenging. Worth it? *Hummm*
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: So you're writing this large lisp application ...
« Reply #12 on: October 08, 2005, 09:54:48 AM »
Hi Michael

Just a thought. If the headers and lines had 3 semicolons and the dump info was wrapped with in-line comments it would let [you] format the file in the VLisp IDE without losing everything .. and would let [you] select the multiiline code block without getting the leading semi-colon in the mix.

Though that may not be an issue with your editor, just with the VLisp IDE.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: So you're writing this large lisp application ...
« Reply #13 on: October 08, 2005, 09:59:21 AM »
I'm not sure I see the value in what you're saying John, but if you define a function using defun-q I suppose you could analyze each statement thusly --

Code: [Select]
(defun-q c:TEST ( / Dump Wait DumpAndWait  a b c d e )

    (defun Dump (x) x)
    (defun Wait ( ) (princ))
    (defun DumpAndWait (x) x)

    (princ "Begin TEST ...\n\n")

    (setq
        a  1
        b  "2"
        c  ((lambda (x) (repeat 8 (setq x (append x x)))) '(1 2 3))
        d  (ssget "x")
    )

    (dump 'a)

    (dump 'b)

    (dump 'c)

    (dump 'd)

    (cond
        (   (eq 'pickset (type d))
            (dump (setq e (ssname d 0)))
            (dump (vlax-ename->vla-object e))
        )
    )

    (princ "End TEST ...\n\n")

    (princ)

)

Code: [Select]
(mapcar '(lambda (lst) (mapcar 'dump lst)) c:test)
Then spews accordingly --

(I'll refrain from posing it as it's no small dump).

You could make the lambda portion of the code above, that is '(lambda (lst) (mapcar 'dump lst)) more elaborate, but I'm really not seeing the value of this (beyond the joy of abstration of course).
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: So you're writing this large lisp application ...
« Reply #14 on: October 08, 2005, 10:08:45 AM »
Hi Michael

Just a thought. If the headers and lines had 3 semicolons and the dump info was wrapped with in-line comments it would let [you] format the file in the VLisp IDE without losing everything .. and would let [you] select the multiiline code block without getting the leading semi-colon in the mix.

Though that may not be an issue with your editor, just with the VLisp IDE.

Hmmm, I don't use the VLIDE so I'm not sure what you mean exactly, "without losing everything". Regarding "select the multiiline code block without getting the leading semi-colon in the mix" doesn't the vlide let you do columnar selection?

I would note that, because I wanted consistant output I patterned all my actual data output to match the formatting vlax-dump-object. While I could write my own version of vlax-dump-object I didn't see the value of that at the time. Hmmm.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst