Programming Course |
Chapter 2Basic Programming Concepts Lisp I - Introduction |
LISP is a computer programming language and is considered by many to be easy to learn and fun to use. In general, a computer program is defined by a sequence of instructions that, when executed, perform a specific task. Each valid instruction is made up of a number of symbols and operations that can occur only in defined patterns. These symbols and operations define the vocabulary of the programming language. Its syntax specifies the valid patterns.
The instructions in a LISP program are termed LISP expressions. Every LISP expression is specified as a list enclosed in parentheses. A LISP expression can be executed directly by an interpreter program and the results displayed on the screen. Thus two steps are involved in this process: writing LISP expressions and passing them to the LISP interpreter for evaluation.
In this course, the LISP interpreter available with the AutoCAD program will be used. Whenever you start AutoCAD, this interpreter is running in the background. When you type a valid LISP expression, it is passed to the LISP interpreter for evaluation. Since AutoCAD is designed to be an interactive graphics application, it provides a number of specialized graphics functions in LISP which are not part of the standard LISP language. The enhanced version of the language available in AutoCAD is known as AutoLisp.
Start AutoCAD by typing acad in any shell window. Once AutoCAD is properly loaded, bring the AutoCAD text window into the foreground by hitting the F1 key. With this larger window available, proceed with the following sections.
A LISP expression is made up of atom(s) and list(s). Atoms can be integer numbers such as 3, 27, -88; floating-point numbers, e.g., 2.34, -0.9, 123.333; or symbols like X, name, My_Name. A list consists of a left parenthesis, followed by zero or more atoms (or lists), and a right parenthesis as in the following: (2 name -3.56) or ().
A number of operations are predefined in LISP like the following arithmetic operations. An operation is defined by a symbol (e.g. +, -) which signifies a function to be performed (e.g. addition, subtraction) on specified atoms.
(+ num1 num2) This operation returns the sum of all specified numbers.
(- num1 num2) This operation subtracts the second number from the first and returns the result.
(* num1 num2) This operation returns the product of two numbers.
(/ num1 num2) This operation divides the first number with the second and returns the quotient.
In the above operations, symbols +, -, *, and / specify functions, and the numbers can be any numeric values on which the functions are carried out by the LISP interpreter. If you mix integer and floating-point numbers in an arithmetic operation, the result returned will be a floating-point number! Further, note that the number of arguments to each of these operations is not limited to only two numbers.
Examples: Enter the following expressions and check the results.
(+ 23 34) => 57
(+ 3.0 12) => 15.0
(- 30.6 25) =>
(- 25 10) =>
(* 12 3) =>
(* 12 3.0) =>
(/ 12 5) =>
(/ 12 5.0) =>
Try these operations with more than two numbers as arguments.
A symbolic atom, e.g., X, name, My_Name, may be used to store some value, i.e., another symbolic atom, a number, character value, or a list. A symbolic atom with a value assigned to it can be evaluated, returning the value it is assigned. Such symbolic atoms are referred to as variables since they can be assigned different values.
An assigment operation assigns a value to a symbolic atom. The simplest assigment operation in LISP is setq.
(setq sym val) This operation assigns the value of the second argument to the first argument.
Examples: Enter the following expressions exactly as shown. Note the quote (') character before the list. Its meaning will be explained in Kapitel 3; for the moment remember to put a quote before any list that is to be passed to a LISP function.
(setq a_float 23.5678) => 23.5678
(setq an_integer -23567) =>
(setq a_list '(a b c)) =>
A variable may be evaluated by simply passing it to the interpreter. In AutoLisp, you can retrieve the value of a variable by typing exclamation mark (!), followed by the variable name, without any space between the two. For example:
!a_float => 23.5678
!an_integer =>
!a_list =>
The examples above should make it clear that once a variable is assigned some value, that variable can be used whenever the value it refers to is needed.
It is also possible to set up variables that do not have any value, this is signified by a special symbol nil. Note that assigning 0 (zero) is not the same as assigning nil to a variable since zero is still a valid value!
Example: (setq a_variable nil) will set up a symbol a_variable that does not have any value assigned to it. Since it is declared, it can be evaluated and the result of evaluation will be nil.
It is also possible to have lists which are empty, i.e. they do not contain any atoms, just left and right parentheses. These are known as null lists.
Example: (setq an_empty_list '()) will set up a null list.
Expressions in LISP are evaluated by an interpreter which may return a value or, simply, T or nil. If a value is returned, it is either assigned to some symbolic atom (e.g. a variable) or it is the result of a function (e.g. car returns the first element in a list). The other two results, T and nil, are special. They imply true or false. In very general terms, if an expression is evaluated successfully, it returns T, otherwise nil is returned. Everything that is not nil is T. Do not use T or t as a variable!
The following section introduces a set of predefined functions, which allow you to test atoms and their values for truth or falsity.
The following predefined operations in LISP allow you to compare values of atoms.
(= atom1 atom2) Returns T if all the atoms are equal, otherwise it returns nil. Atoms can only be numbers and strings, not lists.
(/= atom1 atom2) Returns T if all the atoms are not equal, otherwise it returns nil. Atoms can only be numbers and strings, not lists.
(< atom1 atom2) Returns T if the first atom is less than the second atom, otherwise it returns nil.
(<= atom1 atom2) Returns T if the first atom is less than or equal to the second atom, otherwise it returns nil.
(> atom1 atom2) Returns T if the first atom is greater than the second atom, otherwise it returns nil.
(>= atom1 atom2) Returns T if the first atom is greater than or equal to the second atom, otherwise it returns nil.
Examples: Evaluate the following expressions exactly as shown, including the double quote (") character enclosing strings.
(= 3 3.0) => T
(/= 2 3 4 8) => T
(= "ab" "ab") => T
(< 1 3 7) =>
(< 2 4 4 7) =>
Other logical operations predefined in LISP allow you to find out what kind of atoms are in use and what values are assigned to them.
(zerop item) Returns T if item is an integer or floating-point number which evaluates to zero. Otherwise it returns nil.
(minusp item) Returns T if item is an integer or floating-point number and evaluates to a negative value. Otherwise it returns nil.
(listp item) Returns T if item is a list, otherwise it returns nil.
(atom item) Returns T if item is anything other than a list, otherwise it returns nil.
(null item) Returns T if item is bound to nil, otherwise it returns nil.
Examples: Evaluate the following expressions exactly as shown, including the quote (') character.
(setq a_num 4.5) =>
(setq a_char 'w) =>
(setq a_list '(a b c)) =>
(zerop a_num) =>
(zerop a_char) =>
(minusp a_num) =>
(listp a_char) =>
(listp a_list) =>
(atom a_num) =>
(atom a_list) =>
(null a_list) =>
LISP provides a few operations to check for equality for different argument types and types of equality. The equality operation ('=') we have already encountered above.
(= atom1 atom2) Returns T if all the atoms are equal, otherwise it returns nil.
(equal expr1 expr2)
Returns T
only if expr1
and expr2
evaluate to the same (equal) values. Otherwise it returns nil.
(eq expr1 expr2) Returns T only if expr1 and expr2 are bound to the same object, i.e. they are identical expressions. Otherwise it returns nil.
Examples:
(setq f1 '(a b c)) =>
(setq f2 '(a b c)) =>
(setq f3 f2) =>
(equal f1 f2) =>
(equal f1 f3) =>
(eq f1 f2) =>
(= f1 f2) =>
(eq f2 f3) =>
(= f2 f3) =>
LISP provides a few boolean operations in order to combine logical expressions together.
(not item) Returns T if item evaluates to nil, otherwise it returns nil. It has the effect of negating the truth or falsity of item.
(and item1 item2 ...)
Returns nil
if any item is found to be a nil
expression (i.e. if any argument evaluates to nil),
otherwise it returns T.
This operation evaluates arguments from left to right.
(or item1 item2 ...)
Returns T
if any item is found to be a non-nil
expression (i.e. if any argument evaluates to non-nil),
otherwise it returns nil.
This operation evaluates arguments from left to right.
This exercise extends on Exercise 1 and uses variables to specify some of the arguments to AutoCAD commands. We encourage you to experiment with different shapes generated by the same macros, by altering the variables' values.