Author Topic: Abort and return to command prompt  (Read 6057 times)

0 Members and 1 Guest are viewing this topic.

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Abort and return to command prompt
« on: August 08, 2012, 05:05:30 PM »
In C# you can use Return to cancel out and return to command prompt, how do you do this in LISP?
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: Abort and return to command prompt
« Reply #1 on: August 08, 2012, 05:10:51 PM »
Nevermind, I found it
(exit)
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Abort and return to command prompt
« Reply #2 on: August 08, 2012, 08:17:01 PM »
I find it a rare occasion that I need EXIT?
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

danallen

  • Guest
Re: Abort and return to command prompt
« Reply #3 on: August 08, 2012, 08:42:03 PM »
if a DCL can't be found? Saves having a wrapping if statement.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Abort and return to command prompt
« Reply #4 on: August 08, 2012, 08:53:58 PM »
There is a difference in functionality :

.NET return
returns control to the calling method and can optionally return a value.

the lisp (exit)
returns the error message quit/exit abort and quits to the AutoCAD Command prompt.
.... it's handy to have a good *error* routine so that the environment will be cleaned up.
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.

BlackBox

  • King Gator
  • Posts: 3770
Re: Abort and return to command prompt
« Reply #5 on: August 08, 2012, 10:25:23 PM »
As Kerry has suggested, I use a localized *error* sub-function for Commands that either change settings, or create external objects that must be released, in addition to ending an undo mark when applicable.

In combination with, or in lieu of, I usually use some sort of test function (IF + AND being my most common) to only perform the minimal task(s) necessary before the automated portion of my code. Less to 'handle' if the user hits escape.

HTH
"How we think determines what we do, and what we do determines what we get."

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Abort and return to command prompt
« Reply #6 on: August 09, 2012, 03:24:37 AM »
You could use the vl-exit-with-value to get something similar to C#/C++'s return keyword. Unfortunately though it only works from inside a compiled VLX using a separate namespace (if you use it inside the document namespace - i.e. a same namespace VLX or a FAS/LSP file - it acts like exit but without calling the *error* function or returning a value)  :| ... why that should be you'd have to ask ADesk. My guess is it "exits the namespace, rather than the defun". Same goes for the vl-exit-with-error it seems. At least from my quick tests here in Vanilla 2012:
Code - Auto/Visual Lisp: [Select]
  1. (defun test1 ()
  2.   (vl-exit-with-value "testing vl-exit-with-value")
  3.   1)
  4.  
  5. (defun test2 ()
  6.   (vl-exit-with-error "testing vl-exit-with-error")
  7.   2)
  8.  
  9. (defun c:test (/ *error*)
  10.   (defun *error* (msg) (princ "\nError:\t") (princ msg) (princ))
  11.   (princ (test1))
  12.   (princ (test2))
  13.   (princ))
Both those simply exit to command prompt without returning anything or calling the localized *error* defun at all.

I'd go with Kerry & RM's idea though! There's nothing worse than a user finding his OSnaps turned off after using your custom command. Even in C#/C++ you need to watch for this. If your defun doesn't alter stuff which should revert back, then you may not need to exit cleanly - but there's many times that you'd set some sysvar to make your programming work less or to make the user-interface more to your liking. In which case an error-handler is an absolute MUST.

Actually there's some debate about the use of return / break to stop a function / loop halfway through (even in C/C++/C#). Some deem it a form of "lazy programming". Their main gripe is exactly this "cleanup" idea - though they tend to use memory leaks as an example (which is less of an issue in lisp).

E.g. If your C function allocates memory dynamically (say using malloc or in C++ new) you should either return the pointer to that allocated memory or release it using free / delete. It just becomes very easy to forget to do so if you use return / break somewhere halfway through your code. I mean you look through your code and see that you've written the free / delete so memory shouldn't "leak". But you miss the line where you return / break earlier from the function / loop - if that return/break is reached the memory is never de-allocated, making your function eat RAM every time it's used.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: Abort and return to command prompt
« Reply #7 on: August 09, 2012, 08:05:59 AM »
I find it a rare occasion that I need EXIT?

Ditto, I can't remember ever using it...

owenwengerd

  • Bull Frog
  • Posts: 451
Re: Abort and return to command prompt
« Reply #8 on: August 09, 2012, 10:39:06 AM »
Many years ago Tony and I argued in a very long thread about using (exit). I think that was on the AutoCAD discussion groups, but maybe it was on CompuServe. I use (exit) frequently, or at least I used to when I still wrote a lot of lisp functions.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: Abort and return to command prompt
« Reply #9 on: August 09, 2012, 10:39:45 AM »
Somewhat contrived use of (exit):

Code: [Select]
(defun _Document_Has_XRefs ( document / result )

    (vl-catch-all-apply
        (function
            (lambda ( )
                (vlax-for block (vla-get-blocks document)
                    (if (eq :vlax-true (vla-get-isxref block))
                        (progn
                            (setq result T)
                            (exit)
                        )
                    )
                )
            )       
        )       
    )

    result

)

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

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Abort and return to command prompt
« Reply #10 on: August 09, 2012, 10:44:37 AM »
Quote
but maybe it was on CompuServe.
Now you are showing your age.  8-)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

dgorsman

  • Water Moccasin
  • Posts: 2437
Re: Abort and return to command prompt
« Reply #11 on: August 09, 2012, 11:30:23 AM »
I usually have a lot of "stuff" going on in the LISP functions, and trying to write error handlers to clean up everything everywhere is somewhat tedious (I use a global handler plus standardized handling for for general clean-up).  So I reserve (exit) calls to signal the somethings-REALLY-wrong-here happenings.
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Abort and return to command prompt
« Reply #12 on: August 09, 2012, 12:57:35 PM »
I'm in agreement, exit may be used - it exists after all. It's just that you need to take note that stuff not handled by the garbage collector needs to be handled in the error handler. Whether you create a localized *error* or a common global version is your choice - as long as you don't run into situations like sysvars staying with temporary values, or vla-SelectionSets not deleted, or external ActiveX objects not released - those need to be handled by your error routine(s) if you do use exit. I'd actually say they need to be handled even if you don't use exit - it's just safer that way.

For me, the exit is rather useless - it's more like the abort / exit functions of C++. If it worked exactly as the C return keyword works, then it might have been more useful. As it stands, exit means (to me at least) that something's gone wrong and I need to cancel everything (exactly as if the user pressed ESC).
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

BlackBox

  • King Gator
  • Posts: 3770
Re: Abort and return to command prompt
« Reply #13 on: August 09, 2012, 01:02:48 PM »
As it stands, exit means (to me at least) that something's gone wrong and I need to cancel everything (exactly as if the user pressed ESC).

... And this is where I chose to rely on *error* instead, as if the user pressed ESC, then anything needing to be handled (i.e., sysvars, external objects, etc.) are handled regardless.

For successful completion of code execution I send (*error* nil), whereas 'if' certain criteria is not met first, a CONDitional 'else' expression is used to report to the user what they did wrong (also using *error*, simply changing the MSG argument).
"How we think determines what we do, and what we do determines what we get."

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: Abort and return to command prompt
« Reply #14 on: August 09, 2012, 01:05:30 PM »
What I am doing is checking a value for inserting a switch in vertical space.  What I needed was a way to tell the operator they attempted to insert a part below the NESC safety clearance.  Here is the code

Code: [Select]
(if (= (strcase BsHgt) "LOW")
    (progn
      (if (< *LOWBUS* 98)
   (progn
     (aLERT "Too Low!")
     (exit)
   )
      )


    )
  )


Now that we have mentioned the error routine, I dont have one.  I rarely write in LISP, so I could use good examples.
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)