AutoLISP Lesson #7 - PROGRAM CONTROL
Relational operators
= (= atom atom ...)
(= 3 2) ;Returns nil
(= 3 3) ;Returns T
(= 3 3 3) ;Returns T
Determines if a list of atoms is numerically equal to each other. This operator will work for strings as well as numbers. If you are having trouble getting two values you know are equal to return as equal you may want to use the "eq" or "equal" functions.
/= (/= atom atom ...)
(/= 3 2) ;Returns T
| (/= 3 3) ;Returns nil
Determines if two atoms are not numerically equal to each other. This operator works with strings as well as numbers. If more than two arguments are supplied to the "/=" operator the function is "undefined".
< (< atom atom ...)
(< 3 2) ;Returns nil
(< 2 3) ;Returns T
(< 2 3 4) ;Returns T
Determines if a list of atoms is numerically less than each other. This function returns true if each atom is numerically less than the atom on its right.
<= (<= atom atom ...)
(<= 3 2) ;Returns nil
(<= 2 3) ;Returns T
(<= 3 3) ;Returns T
Determines if a list of atoms is numerically less than or equal to each other. Returns true if each atom is numerically less than or equal to the atom on its right.
> (> atom atom ...)
(> 3 2) ;Returns T
(> 2 3) ;Returns nil
(> 3 3) ;Returns nil
Determines if a list of atoms is numerically greater than each other. Returns true if each atom is numerically greater than the atom on its right.
>= (>= atom atom)
(>= 3 2) ;Returns T
(>= 2 3) ;Returns nil
(>= 3 3) ;Returns T
Determines if a list of atoms is numerically greater than or equal to each other. Returns true if each atom is numerically greater than or equal to the atom on its right.
eq (eq exp1 exp2)
Determines if two expressions are identical to each other. For the expressions to be true they must be bound to the same object. If the expressions are bound to the same object the function will return true.
Example
Assignments:
(setq set1 '(a b c))
(setq set2 '(a b c))
(setq set3 set2)
Tests:
(eq set1 set3) ;Returns nil
;set1 and set3
;are not the
;same list
(eq set2 set3) ;Returns T
;set2 and set3
;are exactly
;the same list
equal (equal exp1 exp2 [fuzz])
(equal 1.0000 1.0001) ;Returns nil
(equal 1.0000 1.0001 0.001) ;Returns T
Determines if two expressions evaluate to the same thing. The two expressions don't have to be identical here. They only have to evaluate to the same value.
Two numbers or point list that look identical may or may not evaluate to being equal, that is why this function adds the "fuzz" factor to the test. You can give an amount by which the two expressions can be off from each other, and still be considered equal.
Conditional operators
Conditional evaluates expressions. If "testexp" does not return nil, then "if" evaluates "thenexp", else it evaluates "elseexp" if given, or returns nil if no "elseexp" was given.
while (while testexp exp ...)
Evaluates the "exp" while the "testexp" remains true. While evaluates "testexp" and if "testexp" is true it evaluates all expressions enclosed in the loop. It then reevaluates "testexp", if "testexp" is still true it goes through the loop again. This continues untill "testexp" evaluates to nil.
cond (cond (test1 result1 ...) ...)
Evaluates "result1" if "test1" is found to be true. This function accepts any number of list as arguments. It evaluates the first item in each list until one of these items returns a value other than nil. When it gets a value other than nil, it evaluates the "result1" expression(s). If it gets a value other than nil from a list and there is only one expression in the list, it returns the value of the expression.
Predicates
and (and exp1 exp2 ...)
Returns the logical AND of a list of expressions. If any of the expressions in the argument list evaluate to nil this function ceases operation and returns nil.
or (or exp1 exp2 ...)
Returns the logical OR of a list of expressions. This function evaluates the expressions from left to right, and upon finding an expression that evaluates to a value other than nil it ceases operation and returns "true".
atom (atom 'symbol)
Returns true if the symbol points to an atom. Otherwise nil is returned. This function evaluates the symbol and if it evaluates to anything other than a list, returns true. Anything that is not a list is an atom.
boundp (boundp 'symbol)
Returns true if the symbol has a value bound to it. If no value is bound to the symbol, it is automatically created and is bound to nil.
listp (listp symbol)
Returns true if symbol evaluates to a list, otherwise it returns nil.
minusp (minusp symbol)
Returns true if symbol is a number less than 0, otherwise returns nil.
not (not symbol)
Returns true if the symbol is nil, otherwise returns nil.
null (null symbol)
Returns true if the symbol is bound to nil, otherwise returns nil.
numberp (numberp symbol)
Returns true if the symbol is an integer or a real number, otherwise returns nil.
zerop (zerop symbol)
Returns true if the symbol is an integer or a real number and evaluates to 0, otherwise it returns nil.
Using the IF function
(if (= test1 true1)
(do_this1))
(if (= test2 true2)
(do_this2))
By writing the normal case first we can read through the normal flow without having to worry about what we are going to do if it turns out false. Now once we know how we want things to work we can add the code to deal with the exceptions.
(if (= test1 true1)
(do_this1)
(else_do_this1))
(if (= test2 true2)
(do_this2)
(else_do_this2))
The normal case for program flow should always follow the "if", the else statement should only be executed if the normal case is not true. This way our program doesn't have to slog through exceptions to get to what we really want to happen. It also makes it easier for maintenance programmers to tell what our logic was when we wrote the code.
Another thing to watch for when programming "if" statements are to branch correctly on equality checks. Be sure when using <, >, <=, and >= statements that the expressions you are comparing are breaking at the right point. Don't use a < when you really need a <=. It is sometimes very easy to get off by one.
Most "if" statements need an else clause, so if you write an "if" statement and think you don't need an else think about it again, you just might find you need one.
If & Boolean functions
(if (or (and (< (ascii symbol) 69)(> (ascii symbol) 64))
(and (< (ascii symbol) 101))(> (ascii symbol) 96)))
(do_this))
Or I could write it like this.
(if (btwn_a_d)
(do_this))
I would then write a boolean style function with all the code to check whether the string was between a & d in it. As you can see the second way of writing the function is much clearer. That's not the only thing I gain from writing it this way, I also can add code to the check
Function to make sure the input was a character and not some data type I was not looking for.
Conditional statements
(cond
((is_alpha symbol) (print symbol))
((is_numeric symbol) (* symbol 2)))
Kind of a short example but I think you can see where I'm heading with this. The code above is clear and easy to read.
At the end of the condition statement you can put a default case that will evaluate if all the other cases fail. Here you can put any code you wish to run in an error trapping capacity. Usually if none of the cases work, something is wrong, and something needs to be done to fix it. You create a default statement by forcing the last list in the condition statement to be true. It is written as follows.
(cond
((is_alpha symbol) (print symbol))
((is_numeric symbol) (* symbol 2))
(T (fix_error))
Try not to use condition statements too liberally, they can really make a mess out of your code. Lists should be used for storing variable values and assigning them after the case statement finds out which case is true. Write the condition statement to test which case you have then run a function to assign variables stored somewhere else. A condition statement should be used to test conditions not assign variables.