Introducing AutoLISP

Featuring

Understanding the AutoLISP Interpreter and Evaluation

Expressions and Arguments

Variables and Data Types

Manipulating Lists with Functions

Get Functions

If you have never programmed a computer before, you may think that learning AutoLISP will be difficult. Actually, when you use a program such as AutoCAD, you are, in a sense, programming your computer to create and manipulate a database. As you become more familiar with AutoCAD, you may begin to explore the creation of linetypes and hatch patterns, for example. Or you may customize your menu to include your own specialized functions and macros. (Macros are like scripts that the computer follows to perform a predetermined sequence of commands.) At this level, you are delving deeper into the workings of AutoCAD and at the same time programming your computer in a more traditional sense.

Using AutoLISP is really just extending your knowledge and use of AutoCAD. In fact, once you learn the basic syntax of AutoLISP, you need only to familiarize yourself with AutoLISP's built-in functions to start writing useful programs. (AutoLISP's syntax is the standard order of elements in its expressions.) You might look at AutoLISP functions as an extension to AutoCAD's library of commands. The more functions you are familiar with, the better equipped you are for using the program effectively.

AutoLISP closely resembles Common LISP, the most recent version of the oldest artificial intelligence programming language still in use today. AutoLISP is essentially a pared down version of Common LISP with some additional features unique to AutoCAD. Many consider LISP to be one of the easiest programming languages to learn, partly because of its simple syntax. Since AutoLISP is a subset of common LISP, it is that much easier to learn.

In this chapter, you will become familiar with some of the basic elements of AutoLISP by using AutoLISP directly from the AutoCAD command prompt to perform a few simple operations. While doing this, you will be introduced to some of the concepts you will need to know to develop your own AutoLISP applications.

Understanding the Interpreter and Evaluation

AutoLISP is accessed through the AutoLISP interpreter. When you enter data at the AutoCAD command prompt, the interpreter first reads it to determine if the data is an AutoLISP formula. If the data turns out to be intended for AutoLISP, then AutoLISP evaluates it, and returns an answer to the screen. This process of reading the command prompt, evaluating the data, then printing to the screen, occurs whenever anything is entered at the command prompt and is an important part of how AutoLISP functions.

In some ways, the interpreter is like a hand-held calculator. Just as with a calculator, the information you wish to have AutoLISP evaluate must follow a certain order. For example, the formula 0.618 plus 1 must be entered as follows:

(+ 0.618 1)

Try entering the above formula at the command prompt. AutoLISP evaluates the formula (+ 0.618 1) and returns the answer, 1.618, displaying it on the prompt line.

This structure-+ 0.618 1-enclosed by parentheses, is called an expression and it is the basic structure for all AutoLISP programs. Everything intended for the AutoLISP interpreter, from the simplest expression to the most complex program, must be written with this structure. The result returned from evaluating an expression is called the value of the expression.

The Components of an Expression

An AutoLISP expression must include an operator of some sort followed by the items to be operated on. An operator is an instruction to take some specific action such as adding two numbers together or dividing one number by another. Examples of mathematical operators include the plus sign (+)for addition and forward slash (/) for division.

We will often refer to the operator as a function and the items to be operated on as the arguments to the function or simply, the arguments. So, in the expression (+ 0.618 1), the + is the function and the 0.618 and 1 are the arguments. All AutoLISP expressions, no matter what size, follow this structure and are enclosed by parentheses.

Parentheses are important elements of an expression. All parentheses must also be balanced, that is, for each left parenthesis, there must be a right parenthesis. If you enter an unbalanced expression into the AutoLISP interpreter, you get the following prompt:

((_>

where the number of parentheses to the left is the number of parentheses required to complete the expression. If you see this prompt, you must enter the number of closing parentheses indicated in order to return to the command prompt. In this example, you would need to enter two right parentheses to complete the expression.

Double quotation marks enclosing text must also be carefully balanced. If an AutoLISP expression is unbalanced, it can be quite difficult to complete it and exit AutoLISP. Figure 1.1 shows the components of the expression you just entered.

Figure1.1: The parts of and AutoLISP expression

Note that spaces are used to separate the functions and arguments of the expression. Spaces are not required between the parentheses and the elements of the expression though you can add spaces to help improve the readability of expressions when they become complex. However, it is very important to maintain spaces between the elements of the expression. Spaces help both you and AutoLISP keep track of where one element ends and another begins.

Using Arguments and Expressions

AutoLISP evaluates everything, not just expressions, but the arguments in expressions as well. This means that in the above example, AutoLISP evaluates the numbers 0.618 and 1 before it applies these numbers to the plus operator. In AutoLISP, numbers evaluate to themselves. This means that when AutoLISP evaluates the number 0.618, 0.618 is returned unchanged. Since AutoLISP evaluates all arguments, expressions can also be used as arguments to a function.

For example, enter the following at the command prompt:

(/ 1 (+ 0.618 1))

In this example, the divide function (/) is given two arguments-number 1 and an expression (+ 0.618 1). This type of expression is called a complex or nested expression because one expression is contained within another. So in our example, AutoLISP first evaluates the arguments of the expression, which are the expression (+ 0.618 1) and the number 1. It then applies the resulting value of the expression and the number 1 to the divide function and returns the answer of 0.618047 (see figure 1.2 ).

 

Figure 1.2: Evaluation of a nested expression

Using Variables

Another calculator-like capability of the interpreter is its ability to remember values. You probably have a calculator that has some memory. This capability allows you to store the value of an equation for future use. In a similar way, you can store values using variables.

A variable is like a container that holds a value. That value can change in the course of a program's operation. A simple analogy to this is the title of a government position. The position of president could be thought of as a variable. This variable can be assigned a value, such as Ronald Reagan or Bill Clinton.

Understanding Data Types

Variables can take on several types of values or data types. Here is what some of these data types look like in AutoLISP.

 

DATA TYPE EXAMPLE
Integer 24
Real Number 0.618
String ``20 Feet 6 Inches''
List (4.5021 6.3011 0.0)
File Descriptor <File: a620>
Object Name <Object name: 60000014c>
Selection Set <Selection set: 1>
Symbols Point1
Subrs Setq

 

By separating data into types, the interpreter is better able to determine precisely how to evaluate the data and keep programs running quickly. Also, a computer stores different types of data differently, and so data types help AutoLISP to manage its memory more efficiently. Finally, data types help keep your programming efforts clear by forcing you to think of data as having certain characteristics. The following descriptions give you an idea of what each of these data types are.

Integers and Real Numbers

Integers are whole numbers from -32768 to + 32767. The value of an expression containing only integers is always an integer. For example, the value of the expression
(/ 25 2) is 12. The decimal value is dropped from the resulting value.

Real numbers are numbers that include a decimal value. If the same expression above is written using real numbers, (/ 25.0 2.0), its value will be expressed as the real number 12.5. Integers have a black and white quality about them. 24 will always equal 24. Real numbers (sometimes referred to as reals), on the other hand can be a bit less definite. For example, two real values, 24.001245781 and 24.001245782 are nearly identical but are not equal. If you were to drop the last decimal place in both these numbers, then they would be equal values. This definitive quality of integers makes them more suited to certain types of uses, like counting, while real numbers are better suited to situations that require exacting values such as coordinate values and angles. Also, computations performed on integers are faster than those performed on reals.

You may have noticed that in our previous examples, the real number 0.618 is preceded by a zero and not written as .618. In AutoLISP, real numbers with values between 1.0 and 0.0 must begin with zero. If you do not follow this rule, you will get an error message. Enter the following at the command prompt:

 (+ .618 1)

 Though the above expression looks perfectly normal, the following error message appears:

 error: invalid dotted pair

Most beginners and even some experienced AutoLISP users might be completely baffled by the error message. We will look at what dotted pairs are later in this book but for now, just keep in mind that real values between 1.0 and 0.0 must be entered with a 0 preceding the decimal point.

Strings

The term string refers to text. Strings are often used as prompts in AutoLISP expressions but they can also be manipulated using AutoLISP. For example, using the Strcat AutoLISP function, you could combine two strings, "thirty seven feet" and "six inches", into one string "thirty seven feet six inches". Try entering this:

(strcat "thirty seven feet " "six inches")

The following is returned:

"thirty seven feet six inches"

Lists

Lists are data elements enclosed in parentheses. They are the basic data structure in AutoLISP. A list can be made up of any number of integers, real numbers, strings, and even other lists.

There are two types of lists. Those intended for evaluation and those intended as repositories for data. When a list contains a function as its first element, we can generally assume that it is an expression intended for evaluation. Such a list is often referred to as a form. An example of a list as a repository of data is a list that represents a coordinate location. For example, the list

 (1.2 2.3 4.4)

 contains three elements, an X, Y, and Z coordinate. The first element, 1.2, is the x coordinate, the second element, 2.3 is the y coordinate, and the third element, 4.4, is the z coordinate.

File Descriptors

AutoLISP allows you to read and write text files to disk. File descriptors are used in a program to access files that have been opened for processing. You might think of a file descriptor as a variable representing the file in question. We will discuss this data type in more detail in Chapter 7.

Object Names

Every object in an AutoCAD drawing has a name. The name is an alphanumeric code unique to that object. This name can be accessed by AutoLISP and used as a means of selecting individual objects for processing. Object names are provided by AutoCAD and are not user definable. Also Object names can change from one drawing session to another.

Selection Sets

Just as you can define a group of objects for processing using the AutoCAD Select command, you can also assign a group of objects, or a selection set, to a variable in AutoLISP for processing. Selection sets are given names by AutoCAD.

Symbols

AutoLISP treats everything as data to be evaluated. Therefore, symbols, or names given to variables, are also data types. Symbols are usually text, but they can also contain numbers like Point1 or dx2. A symbol must, however, start with a letter.

Subrs

Subrs are the built-in functions offered by AutoLISP. These functions perform tasks ranging from standard math operations such as addition and subtraction, to other more complex operations such as obtaining information from the drawing database about a specific object.

Atoms

There are really two classes of data, lists and atoms. You have already seen an example of a list. An atom is an element that cannot be taken apart into other elements. For example, a coordinate list can be "disassembled" into three numbers, the x value, the y value, and the z value, but the x, y and z values cannot be taken apart any further. In a coordinate list, the x, y, and z values are atoms. Symbols are also atoms because they are treated as single objects. So, in general, atoms are either numbers or symbols.

Assigning Values to Variables with Setq

Variables are assigned values through the use of the Setq function. As you have seen, a function can be a simple math operator such as plus or divide. A function can also consist of a set of complex instructions to perform more than one activity, like a small program.

The Setq function tells AutoLISP to assign a value to a variable. For example, Try the following exercise to assign the value 1.618 to the variable named Golden:

1. Enter the following at the command prompt:

(setq golden 1.618)

You can now obtain the value of a variable by preceding the variable name by an exclamation point. Now check the value of Golden.

2. Enter

!golden

The value 1.618 is returned. You might think of the exclamation point as another way of saying "Display the contents of."

Setq will assign a value to a variable even if the variable already has a value assigned to it. See what happens when Golden is assigned a new value.

3. Enter the following:

(setq golden 0.618)

Golden is reassigned the value 0.618 and the old value, 1.618, is discarded. You can even reassign a value to a variable by using that variable as part of the new value as in the following expression

(setq golden (+ golden 1))

In this example, Golden is assigned a new value by adding 1 to its current value.

Preventing Evaluation of Arguments

But something doesn't seem quite right in the above example. Earlier, we said that AutoLISP evaluates the Arguments in an expression before it applies the arguments to the function. In the above example, we might expect AutoLISP to evaluate the variable Golden before it is applied to the Setq function. Since Golden is a variable whose value is 0.618, it would evaluate to 0.618. AutoLISP should then try to set 1.618 equal to 0.618, which is impossible. The value returned by the argument (+ golden 1) cannot be assigned to another number (see Figure 1.3).

 

 

Figure 1.3: The expected outcome of setq

 

Here's why the above example works. Setq function is a special function that is a combination of two other functions, Set and Quote (hence the name Setq). As with Setq, the function Set assigns the value of the second argument to the value of the first argument. The Quote function provides a means of preventing the evaluation of an argument. So, both Setq and Set Quote prevent the evaluation of the first argument, which in the above example is the variable Golden.

You could write the above example as

(set quote golden (+ golden 1))

and get the same answer. Or you could abbreviate the Quote function to an apostrophe, as in the following:

(set 'golden (+ golden 1))

and get the same answer. Figure 1.4 shows what happens when you use Set Quote. Any of these three forms work, but since Setq is the most concise, it is the preferred form.

Figure 1.4: The Quote function prevents evaluation of an argument

 

To further illustrate the use of Quote, look at the following expression:

 (setvar "snapunit" (12 12))

 The function in this expression is Setvar. Setvar performs the same function as the AutoCAD setvar command-it changes the settings for system variables. Setvar accepts as its arguments a string value giving the name of the setting to change ("snapunit") and a value representing the new settings (12 12). Here we are attempting to use Setvar to change the snap distance setting to 12 by 12.

Remember that AutoLISP evaluates each argument before it is passed to the function. As with numbers, Strings evaluate to themselves, so the string "snapunit" evaluates to "snapunit". But AutoLISP will also try to evaluate the list (12 12). AutoLISP always tries to evaluate lists as if they are expressions. As you saw earlier, the first element in an expression must be a function. Since the first element of the list (12 12) is not a function, AutoLISP will return an error message (see figure 1.5).

Figure 1.5: An error using Setvar

 

In this situation, we do not want this list (12 12) to be evaluated. We want it to be read "as is". To do this, we must add the Quote function as in the following:

 (setvar "snapunit" '(12 12))

 Now AutoLISP will not try to evaluate (12 12), and Setvar will apply the list to the snapunit system variable setting.

Quote provides a means to prevent evaluations when they are not desirable. Quote is most often used in situations where a list must be used as an argument to a function. Remember that there are two types of lists, those intended for evaluation and those used to store data. The list (12, 12) stores data, the width and height of the Snap distance. Because (12 12) does not have a function as its first element, it cannot be evaluated. Since AutoLISP blindly evaluates everything, Quote is needed to tell AutoLISP not to evaluate (12 12).

Applying Variables

The variable Golden can now be used within an AutoCAD command to enter a value at a prompt, or within another function to obtain other results. To see how this works, you'll assign the value 25.4 to a variable called Mill.

1. Enter

(setq mill 25.4)

at the command prompt.

Now find the result of dividing Mill by Golden.

2. Enter

 

(/ mill golden)

 

This returns the value 15.698393.

Now assign this value to yet another variable.

3. Enter

 

 (setq B (/ mill golden))

 

 Now you have three variables, Golden, Mill, and B, which are all assigned values that you can later retrieve, either within an AutoCAD command by entering an exclamation point followed by the variable, or as an argument within an expression.

Our examples so far have shown numbers being manipulated, but text can also be manipulated in a similar way. Variables can be assigned text strings that can later be used to enter values in commands that require text input. Strings can also be joined together or concatenated to form new strings. Strings and numeric values cannot be evaluated together, however. This may seem like a simple statement but if you do not consider it carefully, it can lead to confusion. For example, it is possible to assign the number 1 to a variable as a text string by entering

 (setq text1 "1'')

 Later, if you try to add this string variable to an integer or real number, AutoCAD will return an error message.

The examples used Setq and the addition and division functions. These are three functions out of many available to you. All the usual math functions are available, plus many other functions used to test and manipulate variables. Table 1.1 shows some of the math functions available.

Table 1.1: A partial list of AutoLISP functions

 

MATH FUNCTIONS THAT ACCEPT MULTIPLE ARGUMENTS

(+ number number ...) add
(- number number ...) subtract
(* number number ...) multiply
(/ number number ...) divide
(max number number ...) find largest of numbers given
(min number number ...) find smallest of numbers given
(rem number number ...) find the remainder of numbers

MATH FUNCTIONS THAT ACCEPT SINGLE ARGUMENTS

(1+ number) add 1
(1© number) subtract 1
(abs number) find the absolute value
(exp nth) e raised to the nth power
(expt number nth) number raised to the nth power
(fix real) convert real to integer
(float integer) convert integer to real
(gcd integer integer) find greatest common denominator
(log number) find natural log of number
(sqrt number) find square root of number

FUNCTIONS FOR BINARY OPERATIONS

(~ integer) find logical bitwise NOT of integer
(logand int. int. ...) find logical bitwise AND of integers
(logior int. int. ...) find logical bitwise OR of integers
(lsh int. bits) find logical bitwise shift of int.by bits

Since AutoLISP will perform mathematical calculations, you can use it as a calculator while you are drawing. For example, if you need to convert a distance of 132 feet 6 inches to inches, you could enter

 (setq inch1 (+ 6 (* 132 12)))

at the command prompt. The result of this expression is returned as 1590. The asterisk is the symbol for the multiplication function. The value 1590 is assigned to the variable Inch1, which can later be used as input to prompts that accept numeric values. This is a very simple but useful application of AutoLISP. In the next section, you will explore some of its more complex uses.

Accessing Single Elements of a List

When you draw, you are actually specifying points on the drawing area in coordinates. Because a coordinate is a group of values rather than a single value, it must be handled as a list in AutoLISP. You must use special functions to access single elements of a list. Two of these functions are Car and Cadr. The following example illustrates their use.

Suppose you want to store two point locations as variables called Pt1 and Pt2.

1. Enter the following two lines the command Prompt:

(setq pt1 (list 5 6))
(setq pt2 (list 10 12))

The List function in these expressions combines the arguments to form a list. (You can see this in Figure 1.6).

Figure 1.6: The list function.

These lists are assigned to the variable Pt1 and Pt2. As we have just seen, variables accept not only single objects as their value but also lists. In fact, variables can accept any data type as their value, even other symbols representing other variables and expressions.

2. To see the new value for pt1, enter the following:

 

!pt1

 

The list (5 6) appears.

Now suppose you want to get only the x coordinate value from this example.

3. Enter:

 

(car pt1)

 

The value 5 appears.

4. To get the y value, enter:

 

(cadr pt1)

 

which returns the value 6. These values can in turn be assigned to variables, as in the line

 

(setq x (car pt1))

 

Figure 1.7 may help you visualize what Car and Cadr are doing.

Figure 1.7: Car and Cadr of pt1

 

By using the List function, you can construct a point variable using x and y components of other point variables. For example, you may want to combine the y value of the variable Pt1 with the x value of a point variable Pt2.

5. Enter the following:

(list (car pt2) (cadr pt1))

You get the list (10 6) (see figure 1.8).

Figure 1.8: Deriving a new list from pt1 and pt2

These lists can be used to enter values during any AutoCAD command that prompts for points.

Actually, we have misled you slightly. The two primary functions for accessing elements of a list are CAR and CDR (pronounced could-er). You know that Car extracts the first element of a list. CDR, on the other hand, returns the value of a list with its first element removed.

6. Enter the following at the command prompt:

 

(cdr '(A B C))

 

The list (B C) is returned (see figure 1.9).

Figure 1.9: Using Cdr to remove the first element of a list.

When CDR is applied to the list (A B C) you get (B C) which is the equal to the list (A B C) with the first element, A, removed. Notice that in the above example, the list (A B C) was quoted. If the quote were left out, AutoLISP would try to evaluate (A B C). Remember that AutoLISP expect the first element of a list to be a function. Since A is variable and not a function, you would get the error message:

 

error: null function
(A B C)

 

Now try using CDR with the variable pt1.

7. Enter

 

(cdr pt1)

 

The list (6) is returned.

Remember that anything within a pair of parentheses is considered a list, even () is considered a list of zero elements. Since the value returned by CDR is a list, it cannot be used where a number is expected. Try replacing the CADR in the earlier example with a CDR:

8. Enter:

 

(list (car pt2) (cdr pt1))
(10 (6))

 

You get a list of 2 elements, 10 and (6) (see figure 1.10). Though this is a perfectly legal list, it cannot be used as a coordinate list.

Figure 1.10: Using Car and Cdr together

 

So what exactly is CADR then. CADR is the contraction of CAR and CDR. You now know that CDR returns a list with its first element removed and that CAR returns the first element of a list. So to get 6 from the list held by the variable pt1, you apply CDR to pt1 to get (6) the apply car to (6) as in the following example:

(car (cdr pt1))
6

This CAR-CDR combination is abbreviated to CADR.

(cadr (pt1))
6

Figure 1.11 shows graphically how this works. You can combine CAR and CDR in a variety of ways to break down nested lists. Figure 1.12 shows some examples of other CAR and CDR contractions.

Figure 1.11: How CADR works

Figure 1.12: The CAR and CDR functions combined to extract elements of nested lists

 

Functions for Assigning Values to Variables

So far, you have been entering everything from the keyboard. However, you will most often want to bet information from the drawing area of the AutoCAD screen. AutoLISP offers a set of functions just for this purpose. These functions are characterized by their GET prefix. Table 1.2 shows a list of these Get functions along with a brief description.

Table 1.2: Functions that pause to allow input

FUNCTION DESCRIPTION
Getpoint Allows key or mouse entry of point values. This always returns values as lists of coordinate values.
Getcorner Allows selection of a point by using a window. this function requires a base point value defining the first corner of the window. The window appears, allowing you to select the opposite corner.
Getorient Allows key or mouse entry of angles based on Units command setting for angles. Returns values in radians.
Getangle Allows key or mouse entry of angles based on the standard AutoCAD compass orientation of angles. Returns values in radians.
Getdist Allows key or mouse entry of distances. This always returns values as real numbers regardless of the unit format in use.

 To see how one of these functions works, try the following exercise.

1. Turn your snap mode on by pressing the F9 function key.

2. Turn on the dynamic coordinate readout by pressing the F6 function key.

3. Enter the following at the command prompt:

(setq pt1 (getpoint))

This expression blanks the command line and waits until you enter a point. Just as with any standard AutoCAD command that expects point input, you can enter a relative or absolute point value through the keyboard or pick a point on the drawing area using the cursor. The coordinate of the point you pick will become the value assigned to the variable Pt1 in the form of a list.

4. Move your cursor until the coordinate readout lists the coordinate 4,5 then pick that point.

5. Check the value of pt1 by entering the following:

!pt1

The value (4.0 5.0 0.0) is returned and the command prompt appears once again

Note that a Z coordinate value of 0.0 was added and that all the elements of the coordinate list are reals.

Adding Prompts

All these Get functions allow you to create a prompt by following the function with the prompt enclosed by quotation marks. The following demonstrates the use of prompts in conjunction with these functions.

1. Enter the following expression:

(setq pt1 (getpoint ``Pick the first point:''))

The following prompt appears:

Pick the first point:

 

2. Move your cursor until the coordinate readout reads 3,4 then pick that point.

The Get functions allow you to specify a point from which the angle, distance, or point is to be measured.

3. Enter the following:

 

(setq pt2 (getcorner pt1 ``Pick the opposite corner:''))

 

the following prompt appears:

 

Pick the opposite corner:

 

Pt1 is the point variable that holds the coordinate for the last point you picked. A window appears from the coordinate defined by Pt1.

4. Move the cursor until the coordinate readout reads 6,7 then pick that point.

You can also enter a relative coordinate through the keyboard in the unit system currently used in your drawing. Getangle and Getdist prompt you for two points if a point variable is not provided. Getcorner always requires a point variable (see Figure 1.13).

Figure 1.13: The Getcorner function as it appears on the drawing area

By using the Getpoint and getcorner functions, you can easily store point and angle values as variables. You can then refer to a stored point by entering its variable in response to a command prompt that accepts point input.

5. Issue the line command and at the From point prompt, enter:

!pt1

A rubber-banding line appears from the point previously defined as pt1 just as if you had selected that point manually.

6. Now enter the following:

!pt2

A line is drawn from the point stored by pt1 to the point stored by pt2.

Conclusion

So far, you have been introduced to the AutoLISP interpreter and to some of the terms used and a few of the function available in AutoLISP. You have also been introduced to six basic rules key to the use of AutoLISP. In summary, these rules are:

You have seen how you can store values as variables and how you can use AutoLISP to perform math calculations. You may want to apply this knowledge to your everyday use of AutoCAD. Doing so will help you become more comfortable with AutoLISP and will give you further confidence to proceed with more complex programs.

You have also looked at how lists can be broken down and put together through the CAR, CDR, Quote and List functions. List manipulation can be a bit harry so take some time to thoroughly understand these functions. You may want to practice building lists just to get a better feel for this unusual data type.

In Chapter 2, you will learn how to create an AutoLISP program. You will also learn how to permanently store AutoLISP functions so that they can be later retrieved during subsequent editing sessions.