Author Topic: The definition of "error trapping"  (Read 5876 times)

0 Members and 1 Guest are viewing this topic.

Mark

  • Custom Title
  • Seagull
  • Posts: 28762
The definition of "error trapping"
« on: February 24, 2004, 01:15:25 PM »
I've wanted to write something on error trapping for some time now but could never find a good starting point. So.......... if you have some ideas or code examples that show good error trapping post it here.

Here's one I use all the time.
Code: [Select]

(if (setq ent (entsel "\nSelect Something: "))
  (....do something....)
  ; else, if the user picks nothing
  (....do something else like (exit) or start a loop...)
  )

I think it's a good example anyway!
TheSwamp.org  (serving the CAD community since 2003)

rude dog

  • Guest
The definition of "error trapping"
« Reply #1 on: March 08, 2004, 11:47:54 AM »
been patiently waiting in the shadows for other error trapping techniques.....
where are you big game trappers at?

SMadsen

  • Guest
The definition of "error trapping"
« Reply #2 on: March 08, 2004, 11:54:44 AM »
Let loose some types of game and we'll check out some traps that fit.

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
The definition of "error trapping"
« Reply #3 on: March 08, 2004, 12:07:54 PM »
Well, I find that error trapping is kind of application specific.
For example, I wrote a program one that needed to determine the number of plotters defined for the system. In order to get the plotters I attempted to set the plotter system variable (defunct in 2000+ but still showing) When the plotter number returned an error, I knew how many plotters were defined...
Kind of like
Code: [Select]

(setq increment 0)
(while T
(setvar "plotter" increment)
(setq increment (1+ increment)
)

This ALWAYS generated an error, BUT when it did increment would be set to the last number of the plotters.
I could then present the users with a list of plotters defined...
Code: [Select]

(defun *error* (err)
 (if (= err "AutoCAD variable setting rejected")
  (progn
   (setq count 0)
   (repeat increment
    (setvar "plotid" count)
     (setq pl_list (append pl_list (list (getvar "plotid"))))
     (setq count (1+ count))
   )
  )
 )
 (setq *error* *olderror*)
 (show_plotters)
)


As you can see....(of course this could be more eloquent) that is is really dependent upon what you want to do in your program....
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

JohnK

  • Administrator
  • Seagull
  • Posts: 10625
The definition of "error trapping"
« Reply #4 on: March 08, 2004, 03:59:29 PM »
Mark, I too feel your pain (I dont know where and what to say so im just gonna toss these out there).

I have alot of these in my util's file that I end up using alot. I like to test to "see what im looking at" with my lisp before I change it.

Code: [Select]
;;; variable-p
;;; Test to see if item is a variable or not.
;;; Returns - bool
(defun variable-p (a) (not (null a)))

;;; same-variable
;;; Test to see if two variables are equal.
;;; Returns - bool
(defun same-variable (a b) (and (variable a) (variable b) (eq a b)))

;;; number-p
;;; Tests to see if the given is a number.
;;; returns - bool
(defun number-p (a) (eq (type a) 'INT))

;;; block-p
;;; test to see of given is a block
;;; Returns - bool
(defun block-p (x)
  (and (caddr (nentselp (cadr x)))))


Then there is the subject of testing to see if something is there or not. Here is a brief example about what im talking about. Lets say you have a procedure that excepts an argument to incriment. Something like:
Code: [Select]
(defun inc (num) (1+ num))
Well what happens if the user didnt supply a number at all and your in a situation where you cant realy upon your error trap. so you can set up your procedure to return a "switch" instead.

Code: [Select]
(defun inc (num)
  (cond ((= num nil) '*7*)
        ((= (type num) 'STR) '*7*)
        ((= (type num) 'INT) (1+ num))))


This way your procedure never looses control of the situation and the users enviroment never gets left messed up.

Do any of these make sense?
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

Columbia

  • Guest
The definition of "error trapping"
« Reply #5 on: March 09, 2004, 10:42:55 AM »
There are really 2 subjects here that are very similar but are distinct - error trapping and error handling.

Error trapping is more of an instance specific type of thing and the others here have been doing a good job of giving examples of how to do that.  Therefore I won't go into that.

Typically Error Handling is a more global or broad reaching method for handling errors.  Error handling usually refers to the way a program/function deals with a fatal error (an error which crashes your application/program/function).

AutoCAD/AutoLISP provides an Error Handler that can be changed to suit your own needs.  This function is the *error* function.  A programmer can overwrite this function to suit there own needs.  It takes a single argument.  That argument is the message (string) that AutoCAD sends the function as the result of the fatal stoppage.  There are lots of different messages that this error handler reads, but here are just a few:
"Function cancelled"
"quit / exit abort"
"bad argument type:..."
"too few agruments"

The beauty of this is that with a custom error handler a programmer can give their function an even more integrated look and feel.  For instance, with using the AutoCAD standard *error* function, pressing the ESC key will cause the application to cease any processing and immediately dumping the user to the command line.  What typically happens is that once this happens, any environment variables that the program was supposed only temporarily set, are not reset.  That is where customizing the *error* function comes in.   For instance the brief code below allows the user to crash out (press the ESC key) and have is settings still reset.

Code: [Select]

(defun c:some_application (/ *error*)
  (defun *error* (msg)
    (if
      (not
        (member
          (strcase msg T)
         '("quit / exit abort" "function cancelled" "console break")
        )
      )
      (princ "\nError: " msg)
    )
    ...reset any environment variables or close out any file objects or terminate any dialogs here...
    (princ)
  )
  ... the rest of your app goes here ...
)


Notice that the *error* function is nested within the parent and that it is localized within the parent.  The reason that this is done is that this way the original *error* function is not lost after your function executes.

Something else you should pay attention is the IF NOT statment.  What this is going to do is allow the user to ESC out of the function quietly.  Meaning without an error message or leaving anything undone.

This is a good practice to employ in your code.  It is as important as making your apps look and feel like standard AutoCAD.  Not only that it really does become a necessity when your programs start to get into the thousands of lines and the complexity becomes higher and higher.

I hope this makes sense to at least some of you out there in the electronic world.  If not, then let me know, and I will attempt to clarify this mumbo jumbo.  *sssssiiiiipppp* ...ahh... need more coffee now...