Author Topic: Using And as If  (Read 5933 times)

0 Members and 1 Guest are viewing this topic.

Ben Clark

  • Newt
  • Posts: 94
Using And as If
« on: January 03, 2018, 11:19:53 AM »
Lately I've seen some autolisp where people are using the and function almost like an if statement. E.g.:

Code - Auto/Visual Lisp: [Select]
  1.      (CONDITIONAL STATEMENT)
  2.  
  3.      (DO THIS)
  4.      (DO THIS ALSO)
  5. )
  6.  

It seems like it has the advantage of avoiding the progn in the if-condition-progn method. It even seems like it can serve as a form of error trapping. If one of the "do this" expressions returns nil, the next expressions won't evaluate. This may or may not be good depending on the application.

Any comments/pitfalls/alternates to this method?

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: Using And as If
« Reply #1 on: January 03, 2018, 11:34:03 AM »
I do it frequently despite (1) may be confusing to others (2) can easily hide errant logic (e.g. (DO THIS) returns nil so (DO THIS ALSO) is not realized).

tl;dr: Be careful; judicious.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Using And as If
« Reply #2 on: January 03, 2018, 11:39:45 AM »
Apart from potentially reducing the readability of the code for those unfamiliar with the structure, I also find it a useful technique in certain circumstances, but the disadvantage of becoming too accustomed to writing code in this way becomes apparent when you discover that other languages don't support short-circuit evaluation...  :lol:

Ben Clark

  • Newt
  • Posts: 94
Re: Using And as If
« Reply #3 on: January 03, 2018, 11:54:42 AM »
I do it frequently despite (1) may be confusing to others (2) can easily hide errant logic (e.g. (DO THIS) returns nil so (DO THIS ALSO) is not realized).

tl;dr: Be careful; judicious.

You're right about being confusing to others. I experienced it first hand until I realized what people were doing.



Apart from potentially reducing the readability of the code for those unfamiliar with the structure, I also find it a useful technique in certain circumstances, but the disadvantage of becoming too accustomed to writing code in this way becomes apparent when you discover that other languages don't support short-circuit evaluation...  :lol:

I'm glad you used the term "short circuit evaluation" because that led me to look into it. Wikipedia has an excellent summary of how different languages support it.

Apparently the founding father of lisp himself created it:

https://en.wikipedia.org/wiki/Short-circuit_evaluation

tombu

  • Bull Frog
  • Posts: 289
  • ByLayer=>Not0
Re: Using And as If
« Reply #4 on: January 03, 2018, 12:46:04 PM »
I use OR in macros to test if a lisp command exists then load it if needed.  As OR only evaluates till the first True if the command exists the code to load the lisp isn't evaluated.
I've seen AND used in routines and it made sense to me, haven't tried it yet though as I can remember.
Tom Beauford P.S.M.
Leon County FL Public Works - Windows 7 64 bit AutoCAD Civil 3D

ronjonp

  • Needs a day job
  • Posts: 7529
Re: Using And as If
« Reply #5 on: January 03, 2018, 12:48:36 PM »
I use AND quite a bit because it usually wraps on one line.  >:D




Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: Using And as If
« Reply #6 on: January 03, 2018, 01:41:18 PM »
It seems like it has the advantage of avoiding the progn in the if-condition-progn method.

No - you dont really avoid using progn - in some cases you might be not sure what some of the evaluations return, see MP's (reply #1) - so more stable wrapping would be:
Code: [Select]
(and
  (CONDITIONAL STATEMENT)
  (progn
    (DO THIS)
    (DO THIS ALSO)
  )
)


If one of the "do this" expressions returns nil, the next expressions won't evaluate.

Yes, thats the "trick" behind it - to test multiple expression(s), before evaluating the next - to prevent any invalid argument errors.
Say you wanted the user to select at first two circles:
Code - Auto/Visual Lisp: [Select]
  1.   (setq circle1 (car (entsel "\nSelect first circle: "))) ; if something is selected, continue..
  2.   (member '(0 . "CIRCLE") (entget circle1)) ; if its a circle, then continue...
  3.   (setq circle2 (car (entsel "\nSelect second circle: "))) ; if something is selected, continue...
  4.   (member '(0 . "CIRCLE") (entget circle2)) ; if its a circle, then continue...
  5.   ; Now do something like match the radiuses/move one of the circles
  6.   ; depending on the amount of evaluations, that no longer require testing (progn) might be required
  7.   ; if we care about the overall boole return use (progn <expressions> T), to report that its been successful
  8. )
  9.  

It even seems like it can serve as a form of error trapping.

Serves a purpose of "argument checking" or "error preventing" would sound more correct IMO.
"error trapping" is a whole different category of lisp.

This may or may not be good depending on the application.

You just must know what you are doing, so that sounds dumb for me - sorry.


Any comments/pitfalls/alternates to this method?

I do it often, as a quick test to start-off some idea for a program/subfunction or just to help someone on the forum.
Sometimes I translate that code using the (cond ( (not <expr>) (prompt <msg>) ) ..) technique, because it looks more final to me.
But personally for me, thats the best, simple and readable approach for argument checking.

Sorry for the lengthy answer, I just find your threads interesting.  :nerdystraight:
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

JohnK

  • Administrator
  • Seagull
  • Posts: 10648
Re: Using And as If
« Reply #7 on: January 03, 2018, 02:03:11 PM »
*sigh* More "boolean functions doing double duty" discussion. Please do not get in the habit of confusing your returns (put some actual thought into designing your functions/procedures). Conversations like this is how I earned a t-shirt from some members. But seriously, every language has it's shortcuts but more often then not you are better off avoiding them most times.

RRB and AIF:
https://www.theswamp.org/index.php?topic=28433.msg340206#msg340206
Case function:
https://www.theswamp.org/index.php?topic=9645.msg123848#msg123848
Let:
https://www.theswamp.org/index.php?topic=38715.msg438171#msg438171
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

Ben Clark

  • Newt
  • Posts: 94
Re: Using And as If
« Reply #8 on: January 03, 2018, 03:16:15 PM »
This may or may not be good depending on the application.
You just must know what you are doing, so that sounds dumb for me - sorry.

I'm not sure this comment was helpful to the discussion. "You just must know what you are doing" is basically the same as "this may or may not be good depending on the application."



Sorry for the lengthy answer, I just find your threads interesting.  :nerdystraight:

Thanks. I'm glad you find them interesting  :-D

Ben Clark

  • Newt
  • Posts: 94
Re: Using And as If
« Reply #9 on: January 03, 2018, 03:27:54 PM »
Conversations like this is how I earned a t-shirt from some members. But seriously, every language has it's shortcuts but more often then not you are better off avoiding them most times.

Using booleans this way doesn't seem like a mere shortcut; I think it has real utility.

JohnK

  • Administrator
  • Seagull
  • Posts: 10648
Re: Using And as If
« Reply #10 on: January 03, 2018, 04:31:55 PM »
Oh sure it does...now. But, just wait.

I spent days/weeks tracking down a seg-fault in a compiler I was writing and spent a major portion of that time undoing all the ternary operators I thought were a good idea at the time (things like that are very easy to miss and track down later). As you spend more and more time reading and fixing your code you learn more and more what you like (soon you start to like your "simpler/earlier programing skills more"). As you spend more time designing your functions you really start to appreciate the little tricks like: "a logical statement can work with objects as well as a symbol" instead of a fancy "(and(or(not(this(that" statement. This is because you will--and you will do this--over complicate your function(s) and your big program will crash at some weird point and you will not figure out why you keep getting a 'T' for a return. Then you figure out that a simple IF or COND is worth the extra two or three lines. ...anyways, this is of course all up to you. You have the final say in what or how you want to do this. I'm just suggesting to take a moment to think about not being too fancy all the time (but that's not saying that you cannot be a little flashy sometimes).

If I may, I'd also like to steer you towards another rabbit hole; code headers. This is a quick version of a header I use for my functions (different language but still relevant).
Code: [Select]
(defun foo (/)
;; FOO                    this is a very useful function for doing something hard
;;
;; ARGS
;; argument1          :          string
;; argument2          :          list
;;
;; RETURN
;; list

Add in maybe a date, author, and an example and you got yourself a nice little header template which should help keep you out of too much trouble.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Using And as If
« Reply #11 on: January 03, 2018, 05:29:12 PM »
Ben,
If you don't mind stepping back into the past you may find this interesting.
http://www.theswamp.org/index.php?topic=13046.msg158557#msg158557
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.

Ben Clark

  • Newt
  • Posts: 94
Re: Using And as If
« Reply #12 on: January 03, 2018, 05:43:50 PM »
Ben,
If you don't mind stepping back into the past you may find this interesting.
http://www.theswamp.org/index.php?topic=13046.msg158557#msg158557

Nice! That was a very informative write up of how to use conditionals.

Thanks for pointing me to that.

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: Using And as If
« Reply #13 on: January 03, 2018, 07:50:35 PM »
Ben,
Heres a simple trick (more like a homework lol) to help you out visualise how different conditionals perform:

Code - Auto/Visual Lisp: [Select]
  1. (if (getpoint "\nPoint: ")
  2.   (alert "true")
  3.   (alert "false")
  4. )
  5.  
  6. ; 'not' function is reversing the evaluation:
  7. ; _$ (not T) >> nil
  8. ; _$ (not nil) >> T
  9. (if (not (getpoint "\nPoint: "))
  10.   (alert "true")
  11.   (alert "false")
  12. )
  13.  
  14.   (getpoint "\nFirst point: ")
  15.   (getpoint "\nSecond point: ")
  16.   (getpoint "\nThird point: ")
  17. )
  18.  
  19.   (getpoint "\nFirst point: ")
  20.   (getpoint "\nSecond point: ")
  21.   (getpoint "\nThird point: ")
  22. )
  23.  
  24.   ( (getpoint "\nFirst point: ") (alert "1") )
  25.   ( (getpoint "\nSecond point: ") (alert "2") )
  26.   ( (getpoint "\nThird point: ") (alert "3") )
  27.   ( (alert "no point") )
  28. )
  29.  
  30. ; 'progn' example:
  31.   (progn
  32.     nil T nil T T nil '(12 32 0) ; <- whatever returns we got from running subfunctions or doing stuff
  33.     (getpoint "\nPoint: ") ; <- only the last evaluation matters
  34.   )
  35.   (alert "true")
  36.   (alert "false")
  37. )
  38.  
  39. ; (and) function performs 'lazy evaluation', this is demonstration of non-lazy evaluation:
  40.   (list
  41.     (getpoint "\nFirst point: ")
  42.     (getpoint "\nSecond point: ")
  43.     (getpoint "\nThird point: ")
  44.   )
  45. )
  46.  
  47. ; (or) function performs 'lazy evaluation', this is demonstration of non-lazy evaluation:
  48.   (list
  49.     (getpoint "\nFirst point: ")
  50.     (getpoint "\nSecond point: ")
  51.     (getpoint "\nThird point: ")
  52.   )
  53. )

Basically you are prompted for three points, use RMB to specify a point, so that evaluation returns value (which would be accepted as true) or LMB to return nil. [RMB = T] [LMB = nil]
Test several times, with different inputs to see how the different conditional functions behave, and I guess you'll be able to visualise how the evaluations will run thru a fragment like this:
Code - Auto/Visual Lisp: [Select]
  1. (and
  2.   (progn (getpoint "\nFirst point: ") T)
  3.   (getpoint "\nSecond point: ")
  4.   (or (getpoint "\nThird point: ") T)
  5.   (cond ( (progn (getpoint "\nFourth point: ") nil) ) ( T ) )
  6.   (not (getpoint "\nFifth point: "))
  7. )

That fragment is just an example, where an experienced eye would understand whats happening (so don't look for any sense in there  :whistling:).
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

JohnK

  • Administrator
  • Seagull
  • Posts: 10648
Re: Using And as If
« Reply #14 on: January 04, 2018, 10:23:27 AM »
Stuff like this may be fun to experiment with but the problem is, most of those examples are not very professional at all (no offense). And if you try to maintain some of those you'll spend more time deciphering then fixing or if you show it to anyone with a real programming education/background they will just chew you up with questions like: "why?".

For example, this would be a `professional-ish' getpoint procedure. True, it's not very fancy or tricky but anyone would be able to read this and troubleshoot it. They can share it on a forum like this (with members who are actually working professional programmers) and it would be perfectly respectable code (no question on it's intent or validity).

Code - Auto/Visual Lisp: [Select]
  1. (defun _getpoint ( nu p / pt )
  2.     ;; get point procedure.
  3.     (while
  4.       (not
  5.         (setq pt
  6.               (cond
  7.                 (p
  8.                   (getpoint p
  9.                             (strcat "\nSelect point number " (itoa nu) ":")))
  10.                 (t (getpoint
  11.                      (strcat "\nSelect point number " (itoa nu) ":")))
  12.                 )
  13.               )
  14.           )
  15.        (princ "\nPlease select a point..."))
  16.      pt
  17.     )
  18.  
  19. ; ... <CODE>
  20.  
  21.   (setq pt1 (_getpoint 1 'nil))
  22.   (_getpoint 2 pt1))))
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org