TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: Hangman on October 18, 2006, 01:59:24 PM

Title: Curious ... Help with lisp code
Post by: Hangman on October 18, 2006, 01:59:24 PM
Can someone tell me the difference between the two examples posted below.

example A:
Code: [Select]
... (if (= (tblsearch "style" "ARCHITXT") nil) (command ".-style" "ARCHITXT" "ARCHITXT.SHX" txtht "0.75" "" "n" "n")) ...

example B:
Code: [Select]
... (cond ( (= (strcase tstyl) "ARCHITXT") (command ".-style" "ARCHITXT" "ARCHITXT.SHX" txtht "0.75" "" "n" "n")) ...

I know one is an 'if' statement and the other is a conditional statement.   :-P
but other than that, example A is doing a table search for the text style, but they both are accomplishing the same thing aren't they ??
So what is example B doing ??
What is the difference ??

Thanks.
Title: Re: Curious ...
Post by: T.Willey on October 18, 2006, 02:02:27 PM
I think you example B isn't complete.  It should be
Code: [Select]
... (cond ( (= (strcase tstyl) "ARCHITXT") nil) (command ".-style" "ARCHITXT" "ARCHITXT.SHX" txtht "0.75" "" "n" "n")) ...
They are doing the same thing.  If you only need to test for one condition, I typically use 'if', if it can have more than to values, I would use 'cond'.

Hope that makes some kind of sense.
Title: Re: Curious ...
Post by: CAB on October 18, 2006, 04:00:13 PM
Here is my take on the subject:

The if statement works like this
Code: [Select]
(if (this is true)
  (then do this)
)

Code: [Select]
(if (this is true)
  (then do this)
  (else do this when false)
)



The (cond) stmt on the other hand executes the all of code following
a true condition and then exits the condition stmt.

Code: [Select]
(cond
  ((= 1 0)
    none of this will get executed
    because the conditions is false
  ) ; end cond 1

  ((= 1 1)
     do all of this because it is true
     and this
     and this
   ) ; end cond 2

   ((= 2 2)
     none of this will get
     executed even if it is true
     because the prior stmt was true
   ) ; end cond 3

   (T
     This is often placed at the last position
     in a condition statement and will be executed
     if all the prior conditions are false
     if any one of the above conditions are true
      this will not be executed
   ) ; end cond 4
) ; end cond stmt


The  OR will process each line as long as they are false, it will quit when true is returned
Code: [Select]
(or (a. is true) ; stop here
     (b. does not get this far)
)

Code: [Select]
(or (a. is false) ; keep going
     (b. do this & if false keep going)
     (c. do this if b was false)
)

So this will work as well with a variable with a value or nil
Code: [Select]
(setq var "Some Text")
(or  var ; Stop here if the var has a value, if nil then keep going
     (setq var "Some Text")
)

The  AND will process each line as long as they are true, it will quit when false is returned
Code: [Select]
(and (a. is true) ; keep going
      (b. do this & if true keep going)
      (c. do this if b was true)
)

Note that AND & OR themselves only return true or nil,
whereas IF and COND will return the value of the  expression.
Code: [Select]
(setq rtn
       (or (+ 3 7) ; returns 10 which is not nil so it passes the test for true
            (+ 2 4 6) ; return 12
       )
)
While the value in rtn is t
Code: [Select]
(setq rtn
       (if (+ 3 7) ; returns 10 which is not nil so it passes the test for true
            (+ 2 4 6) ; return 12
       )
)
The value in rtn is 12
Code: [Select]
(setq rtn
       (if (> 3 7) ; 3 is not > 7 so this returns nil
            (+ 2 4 6) ; return 12
       )
)
The value in rtn is nil because there was no else line to consider
Code: [Select]
(setq rtn
       (if (> 3 7) ; 3 is not > 7 so this returns nil
            (+ 2 4 6)
            (- 10 2)
       )
)
No supprise here, the rtn value is 8

The cond statement works simular to the if
Here is an example I like
Code: [Select]
(initget 0 "Yes No")
(setq ans
          (cond
           ((getkword "\nGive your answer.  [Yes/No] <Yes>: "))
                ("Yes")
          )
)
If the user hits the enter key nil is returned and the cond returns "Yes"
If the user enters text the text is returned






Some examples of  (progn
Note that progn returns the value of the LAST evaluated expression.
Code: [Select]
(if (this is true)
   (progn
        do all of this
        and this
        and this
    )
   (don't do this)
); endif

(if (this is false)
   (don't do this)
   (progn
        do all of this
        and this
        and this
    )
)

So you see the progn is a way to group code together.
The (if) stmt will execute the group of code when true and
will execute the second group of code when false,
if there is a second group of code. If you forget the (progn) only the first
line of code will be executed if true and the rest skipped.
There are other ways to group code together and you will learn them in time.


Outa Gas,
I know it's more that you wanted to know.
See ya.

The (cond) stmt on the other hand executes all of the code following
a true condition and then exits the condition stmt. Remember true is anything not nil.

Code: [Select]
(cond
  ((= 1 0)
    none of this will get executed
    because the conditions is false
  ) ; end cond 1

  ((= 1 1)
     do all of this because it is true
     and this
     and this
   ) ; end cond 2

   ((= 2 2)
     none of this will get
     executed even if it is true
     because the prior stmt was true
   ) ; end cond 3

   (T
     This is often placed at the last position
     in a condition statement and will be executed
     if all the prior conditions are false
     if any one of the above conditions are true
      this will not be executed
   ) ; end cond 4
) ; end cond stmt



Here is a trick for the cond statement when you want to conditionally execute the cond.
Often we see it like this:
Code: [Select]
(if (something is true) ; reminder, 'true' here is really anything (not nil)
  (cond
    ((= 1 1) ...)
    ((= 2 2) ...)
  ) ; end cond stmt
) ; endif

It can be written like this so that if something is not true the first condition is true &
nothing is done but the cond statement is satisfied that it found a true condition.
The processing skips the remaining conditions.
Code: [Select]
(cond
  ((not (something is true))) ; if something is not true stop here
  ((= 1 1) ...)
  ((= 2 2) ...)
) ; end cond stmt



The WHILE function as a conditional loop and continues the loop until the next
expression returns nil. Here we test the value in cnt looking for it to become 0
so that we can exit the while loop. The code within the loop is executed 5 times,
while the cnt value is 0 through 4.
Code: [Select]
(setq cnt 0)
(while (= cnt 5)
  ;;  do some stuff
  (setq cnt (1+ cnt))
)

It can also be written like this and the cnt value is 0 through 4.
Code: [Select]
(setq cnt -1)
(while (= (setq cnt (1+ cnt)) 5)
  ;;  do some stuff
)

Sometimes the condition you want to test is set at the end of the code within
the loop. The code may look like this.
Code: [Select]
(setq continue_loop t)
(while continue_loop
  ;;  do some stuff
  (if (I want to leave the loop is true)
    (setq continue_loop nil) ; flag to exit the loop
  )
)

This can also be written like this:
Code: [Select]
(setq continue_loop t)
(while
  (progn
  ;;  do some stuff
   (not (I want to leave the loop is true)) ; flag to exit the loop
  ) ; progn
)

So you see that when  (I want to leave the loop is true) returns true, the not will
return nil and because it is the last expression in the progn, that is the value the
while sees. It then exits the loop.


Here is a real world example.
This is my solution for entering numbers like key words
The simulated key words would be "90 180 270 -90"
Code: [Select]
(while
  (progn
    (setq rang
           (cond ((getint "\nEnter the rotation angle [90/180/270] <90>"))
                 (90)))
    (if (not (vl-position rang '(90 180 270 -90)))
      (not (prompt "\nError  Angle must be 90 180 270, please re-enter.")))
  )
)

Added a little more. :)
Title: Re: Curious ...
Post by: T.Willey on October 18, 2006, 04:11:07 PM
Very nice Alan.

 <tips hat>
Title: Re: Curious ...
Post by: MP on October 18, 2006, 05:02:19 PM
Very nice Alan.

<tips hat>

x 2, good job!

:)
Title: Re: Curious ...
Post by: Hangman on October 18, 2006, 05:25:29 PM
Wow !!!  Alan, thank you.  Yeah, it was a bit more than I was looking for, but then again, I wasn't sure what I was to expect.  Definately an opportunity to learn more.
Don't take me wrong here, I really do appreciate the info.  It explains why a couple of my routines are not acting as they should, I was not completely understanding the conditional, the or & the and statements.
I was however, looking for some thought on the tblsearch vs cond. situation.  With that info in mind, perhaps I should re-phrase my question.   ^-^

In the If statement, I am doing a tblsearch for the text style.  If it is not available, create it.
In the conditional statement, I am NOT doing a tblsearch, but I am doing the same thing, if it is not available, create it.
How is this accomplished ??
Is the conditional statement recreating the text style regardless, where the If statement is only creating it if it is not there ??

Tim, you put a ... nil) in the example B,
Quote
I think you example B isn't complete.  It should be
Code: [Select]
... (cond ( (= (strcase tstyl) "ARCHITXT") nil) (command ".-style" "ARCHITXT" "ARCHITXT.SHX" txtht "0.75" "" "n" "n")) ...
But the = sign is refering to the "ARCHITXT".  the nil would be one more parenthesis down.  Would the = sign still work for the nil ??
My intention for the code would be to find the  'tstyl ARCHITXT', and replace it.  Here's the bigger picture.
Code: [Select]
(progn
      (cond ( (= (strcase tstyl) "ARCHITXT")
              (command ".-style" "ARCHITXT" "ARCHITXT.SHX" txht "0.75" "" "n" "n")
              (setq txtupd "Textstyle Updated")
            )
;
            ( (= (strcase tstyl) "ARIAL")
              (command ".-style" "ARIAL" "ARIAL.TTF" txht "0.875" "" "n" "n")
              (setq txtupd "Textstyle Updated")
            )
;
            (T
              (ALERT "The Current Text Style is Unrecognized!")
              (ALERT "ARCHITXT Text Style will be substituted!")
              (command ".-style" "ARCHITXT" "ARCHITXT.SHX" txht "0.75" "" "n" "n")
              (setq txtupd "Alternate")
            )
      );end cond
      (if (= txtupd "Alternate")
        (setq txtupd nil))
    );end progn
Perhaps I am wasting time & resources here.  I don't know.  I have several typical details that have an old text style with the same ARCHITXT name.  Instead of fighting the system, I figured I'd just replace the text style with our current.  We are running into more and more clients requesting ARIAL be used as well.  But with this, if STANDARD or some other style is current, the code won't recognize it and put ARCHITXT in.  If ARIAL is needed, it basically throws up a flag to the user so they know to update their text style to ARIAL.

This is a parallel to my question though, and any advice on this would be well received.

So, if the examples A and B are doing the same thing, then wouldn't this also work ??
Code: [Select]
... (if (= (tblsearch "style" (strcase tstyl) "ARCHITXT") nil) (command ".-style" "ARCHITXT" "ARCHITXT.SHX" txtht "0.75" "" "n" "n")) ...
or perhaps
Code: [Select]
... (cond ( (= (tblsearch "style" (strcase tstyl) "ARCHITXT") nil) (command ".-style" "ARCHITXT" "ARCHITXT.SHX" txtht "0.75" "" "n" "n")) ...

Thank you for your thoughts.

<<< Edited for Clarity >>>

AHaaa, there's my question:
How is the conditional statement doing a tblsearch when it is not asked to do it ??  Or could it be that the following is completely disregarded ??
Code: [Select]
... (cond ( (= (strcase tstyl) "ARCHITXT") ...
(from example B)
Title: Re: Curious ...
Post by: CAB on October 18, 2006, 05:49:54 PM
In the cond example the variable  tstyl was previously set to a text style name.
Perhaps the current text style, like this
Code: [Select]
(setq tstyl (getvar "textstyle"))
(cond
  ( (= (strcase tstyl) "ARCHITXT")
     ;; if the previous expression is not nil this will continue to execute here
     (command ".-style" "ARCHITXT" "ARCHITXT.SHX" txht "0.75" "" "n" "n")
     (setq txtupd "Textstyle Updated")
)


Quote
But the = sign is refering to the "ARCHITXT".  the nil would be one more parenthesis down.  Would the = sign still work for the nil ??
My intention for the code would be to find the  'tstyl ARCHITXT', and replace it.  Here's the bigger picture.

the use of (= var nil)  or (= (expression) nil) is not needed & most people do it for there readability.
The reason it is not needed is that anything that is not nil or returns anything except nil will be considered to be TRUE.
Conversely anything that is nil or returns nil will cause the if or cond to pass it by.

I'll be back later....
Title: Re: Curious ...
Post by: John Kaul (Se7en) on October 18, 2006, 07:18:53 PM
The initial ``cond'' statment you posted is not doing a tablesearch, it is mearly looking up the contents of a variable.

Another very good explination for conditionals can be found here.
http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-10.html#%_sec_1.1.6
Title: Re: Curious ...
Post by: T.Willey on October 18, 2006, 07:40:35 PM
What I did was not read carefully enough.  Sorry.

I would just skip the first 'if' statement you posted, as it is not needed, unless you always want that style in there.  You are only not creating it if the 'tstyl' variable is set to 'ARIAL'.
Title: Re: Curious ... Help with lisp code
Post by: CAB on October 19, 2006, 12:09:12 AM
Thanks guys :-)


Hangman,
The cond above is NOT doing the same thing as a table search. It is comparing the variable tstyl to the string "ARCHITXT".
You are saying [is the uppercase of variable tstyl equal to the string "ARCHITXT"]

If you want to see if the style is in the drawing use the following code.
 No need to strcase the variable in the tblsearch as the tblsearch ignores case
 
 It reads like this:
 If the text style in var tstyl is not in the drawing do the cond

Note that the return value from the cond statement is being saved in the variable txtup

 
Code: [Select]
(if (not (tblsearch "style" tstyl "ARCHITXT"))
  (setq txtup
         (cond ((= (strcase tstyl) "ARCHITXT")
                (command ".-style" "ARCHITXT" "ARCHITXT.SHX" txht "0.75" "0" "n" "n")
                "Textstyle Updated"
               )
               ((= (strcase tstyl) "ARIAL")
                (command ".-style" "ARIAL" "ARIAL.TTF" txht "0.875" "" "n" "n")
                "Textstyle Updated"
               )
               (t
                (alert (strcat "The Current Text Style is Unrecognized!"
                               "\nARCHITXT Text Style will be substituted!"
                       )
                )
                (command ".-style" "ARCHITXT" "ARCHITXT.SHX" txht "0.75" "" "n" "n")
                "Alternate"
               )
         ) ; end cond stmt
  )
)
Title: Re: Curious ... Help with lisp code
Post by: Hangman on October 19, 2006, 04:56:56 PM
So, the tblsearch does a search of the drawing for the style, period.  No variables, no if's, no conditionals, it just does the search.
Where the 'if' statement and the 'conditional' statement rely on a variable to do their search.  Well, In essence I mean, as the 'if' statement causes the tblsearch to occur.

They are both doing the same thing, but one way is based on given variables where the other is open to suggestion.

Aaaah.  I am in understanding.  Thank you all for your comments, it has been very enlightening.
Title: Re: Curious ... Help with lisp code
Post by: Kerry on October 19, 2006, 05:01:29 PM
So, the tblsearch does a search of the drawing for the style, period. 

Not actually 'search of the drawing " ...
a table is where the definitions are kept  ... slightly different, but an important distinction.
Title: Re: Curious ... Help with lisp code
Post by: Hangman on October 19, 2006, 05:17:58 PM
Ahhh yes, thank you Kerry.  I remember Tim mentioning the definitions from a post several months ago now that you mention it.  Thanks for the clarification.