A brief introduction to AutoLISP®:
AutoLISP® is a programming language which operates within AutoCAD® and designed for extending and customizing AutoCAD functionality. In short, AutoLISP is used for making AutoCAD shortcuts and timesavers. AutoCAD introduced AutoLISP as an application programming interface (API) in its Release 2.1, in the mid-1980s.
AutoLISP is actually based on the LISP programming language, whose origins date back to the late 1950s. LISP was originally designed for use in Artificial Intelligence (AI) applications, and is still the basis for many AI applications.
http://mylisps.20m.com/
What is AutoLISP?
AutoLISP is the programming language which operates within AutoCAD to enhance and customize its native abilities. It is supplied without additional cost as a standard component of AutoCAD. (If you have AutoCAD, you have AutoLISP.)
AutoLISP can be used to customize AutoCAD in two principal ways. First, AutoLISP can automate repetitive procedures. This saves the user time and can eliminate many errors. Second, AutoLISP can enhance AutoCAD, giving it new commands and features, all the way from doing calculations to creating complete drawings and more.
AutoLISP was developed from the LISP programming language, which has been around for a long time. AutoLISP, while it retains the syntax of LISP, is streamlined to run inside AutoCAD and has many added functions so it can interact with both the AutoCAD commands and the drawing database.
AutoLISP has always been an interpreted language rather than a compiled language, although a programming environment including a compiler is now available. A program can be written with any text editor, saved in a plain ASCII text file, then loaded into memory inside AutoCAD. Once loaded, the program can be run from the Command prompt or from a pull-down menu, just like any other AutoCAD command.
Not only does AutoCAD come with the AutoLISP language already built in, but also with numerous sample AutoLISP programs found in a "sample" directory. Also many more programs are available at a price from third party vendors. And there are also many programs that are available free over the internet. All of these written programs can enhance your productivity with AutoCAD, but you will find that the programs that are most helpful to you are the ones that you write yourself, or the ones you have written to meet your specific needs.
http://courses.home.att.net/autolisp/aconcept.htm
List processing languages such as LISP ("LISP" stands for list processing)
History of LISP
LISP was created in the context of AI (Artificial Intelligence) research. In 1956 John McCarthy developed the foundation for LISP during the Dartmouth Summer Research Project on AI.
During the early 60's, the principal dialect of LISP was Lisp1.5. Then many different dialects and implementations for various computers appeared, including BBNLisp, Interlisp, MacLisp, NIL (New Implementation of Lisp), Franz Lisp, Scheme, Flavors, LOOPS (Lisp Object Oriented Programming System), SPICE-Lisp, and PSL (Portable Standard Lisp). The 70's and early 80's even saw the development of specialized computers known as Lisp Machines which were designed specifically to run LISP programs.
In 1981 many LISP programmers got together to identify the common aspects of certain dialects and thus created Common LISP. By 1984 Common Lisp was considered the de facto standard. Golden Common LISP was developed from Common LISP for the IBM PC, and David Betz developed XLISP, which is the dialect of LISP on which AutoLISP is based.
AutoLISP's Roots in LISP
AutoLISP is a direct descendant of the XLISP dialect of the LISP programming language. In fact, AutoLISP can be considered both a subset and a superset of XLISP. It is a subset since it does not include all the functions contained in XLISP. It is a superset since it contains many functions not found in XLISP. These added functions allow AutoLISP to interact with AutoCAD's drawing database and commands. However, in concept, syntax, and programming style, LISP (XLISP in particular) is clearly the progenitor of AutoLISP.
Basic Continuity
AutoLISP has been included in AutoCAD ever since version 2.18 (January, 1986). Although it has grown, it has maintained its continuity over the years. Each time a new release of AutoCAD comes out, you can expect to find a few new AutoLISP functions. Here are some that have appeared in past releases of AutoCAD:
Release 7 (Version 2.5)
Introduced access to entities in the drawing database.
Release 8 (Version 2.6)
Introduced 3D points and the functions getcorner, getkword, and initget.
Release 9
Introduced the command function and ssget filters.
Release 10
Introduced enhanced functions findfile and load; new functions getenv, handent, and vports.
Release 11
Introduced enhanced function entget; new functions cvunits and entmake.
Release 12
Introduced enhanced functions ssget and initget; new functions alert, getfiled, and textbox, and programmable dialog boxes using the DCL (Dialog Control Language).
Release 13
Introduced several new functions including acad_strlsort, autoload, help, and acad_colordlg.
Release 14
Introduced Visual LISP™, a complete AutoLISP programming environment.
Release 2000
Visual LISP™ now built in.
Naturally, these new functions and enhanced functions are welcomed additions. They represent growth and seldom make the old functions obsolete. For the most part, the old functions work the same in the latest release as in previous releases. In fact, when compared with operating systems, the format of the drawing database, and the user interface, AutoLISP is one of the more consistent aspects of AutoCAD.
http://courses.home.att.net/autolisp/ahistory.htm
These three pages are meant for the absolute beginner - by no means do they cover a complete introduction, just enough to get a beginner started. Part I gives a very brief introduction by starting out with simple expressions written directly at the command prompt in AutoCAD. This method is chosen because it immediately gives the beginner a sense of the tasks that AutoLISP can be used for. Syntax and evaluation start in part II.
About AutoLISP
AutoLISP is a registred trademark of Autodesk Inc. It is a programming language that is used with AutoCAD for automation and customization purposes. AutoCAD was early on given an open architecture that makes it possible to access almost any feature programmatically.
AutoLISP is based on the programming language LISP. The history of LISP dates back to the 50's and is a fascinating story about innovative people with dedications and visions. It can only be recommended to get acquainted with the events that lead to the development of the second oldest programming language still being used. However, this is not the story behind LISP.
Back in 1985, the relatively young corporation Autodesk, who had launched their design package AutoCAD almost 4 years before, began looking around for a programming language to implement. Among other languages they looked at the de facto standard of LISP and the final choice was a subset of Common Lisp (only part of the functionality) based on a portable ANSI C interpreter called XLISP, written by David M. Betz. It was first implemented with a minor upgrade of AutoCAD version 2.18 in January 1986. By the next upgrade, version 2.5 in June same year, AutoLISP had become an established part of AutoCAD. Since then AutoLISP has grown considerably and is fully capable of doing nearly all possible tasks in AutoCAD.
The most recent and major improvements were made in the time between the initial release 14 and AutoCAD 2000. Besides given a whole new interface, called VisualLISP, it was totally rewritten and new functionality was added in order to take advantage of AutoCAD's object model.
LISP is a LISt Processing language. Those familiar with Basic, Pascal or C know that they consist of functions/procedures and different datatypes. In true LISP, functions and procedures can be seen as datatypes themselves - popular speaking, only lists of adresses are processed by the interpreter and it is those adresses that hold the information about further evaluation. Whether this sounds confusing or not, nothing should be holding you back from learning the language - once getting used to the syntax it is actually not difficult to learn, even if you never touched a programming language before.
Quick introduction
- practical examples of using AutoLISP at the command prompt
Unlike all the other programming languages that has since been implemented, AutoLISP has the advantage of still being regarded as an interpreted language by AutoCAD. This means that you can simply write expressions at the command prompt and get immediate results. Even if you never intend to write lisp programs, take a minute of your time, fire up AutoCAD and work through the following examples.
First, let's look at a simple example of how to turn AutoCAD into a quick calculator. At the command prompt write this:
Command: (* 5 40.0)
200.0
Hmmm, what just happened? Writing (* 5 40.0) was not to add a comment to your drawing notes; it was a simple AutoLISP expression in order to multiply the number 5 with the number 40.0, and the result, 200.0, was immediately returned to you.
All AutoLISP expressions are written within a pair of parantheses and the leftmost part within them is the function to be carried out - everything to the right of the function are arguments to the function. So, in this case the asterix is the function name for multiplication and the numbers 5 and 40.0 are the arguments. Very simple, isn't it?
AutoLISP supports all basic four arithmetical operations:
Command: (+ 5 40.0)
45.0
Command: (- 5 40.0)
-35.0
Command: (* 5 40.0)
200.0
Command: (/ 5 40.0)
0.125
In shown order: addition, subtraction, multiplication and division. Just like the notation in a spreadsheet or on your calculator.
Functions themselves can become arguments to other functions. This is called nesting and what is happening is that the deepest nested functions return results to the next level of nested functions and so on. In order to write an equation that employs more arithmetical operations you simply nest the separate equations:
Command: (+ 5 (* 40.0 2))
85.0
This is the same as writing (40.0 * 2) + 5 on a piece of paper. The first evaluated expression is the one most deeply nested which returns a result to the next level and so. Here are some other examples:
Command: (+ 5 (* 40.0 2)(/ 48 8))
91.0
Command: (/ (+ (* 6 40) 10) 25)
10
The first example also nests 2 levels because 5, (* 40 2) and (/ 48 8) are all addends at the same level. In school lingo the equation reads: 5 + (40 * 2) + (48 / 8) = 91. The last expression is a perfect example of nesting 3 levels deep. In school lingo it is the same as ((6 * 4) + 10) / 25 = 10.
So, beside using AutoCAD as a very expensive calculator, what can AutoLISP be used for? For one thing you can use AutoLISP expressions in any command that accepts a number. Let's look at the OFFSET command. How often have you used DIST to get a distance, then grabbed your calculator, typed in the distance and divided it with a certain interval, then back to the screen, invoked the OFFSET command and typed in the result? Try this instead:
Command: DIST
Specify first point: pick a point as you normally would
Specify second point: again, pick a point
3500.0
Command: OFFSET
Specify offset distance or [Through] : (/ 3500.0 12.5)
280.0
Select object to offset or : execute the command
Let's see what just happened. You used the DIST command to get the distance that had to be divided, nothing unusual here - the result of 3500.0 units is just an example. In the OFFSET command, instead of grabbing your calculator you asked AutoCAD to calculate the offset distance and, more importantly, AutoCAD actually delivered the result to the OFFSET command directly. To prove it, invoke OFFSET once more or inspect the system variable OFFSETDIST; it will show the distance 280.0 which, of course, is the result of 3500 divided by 12.5.
Moving on, even if we still have to measure a distance to be divided before offsetting can be done, we can bypass the DIST command entirely. In the following, don't worry about the AutoLISP function GETDIST - it simply does what the DIST command does, except it does it using the built-in AutoLISP interpreter:
Command: OFFSET
Specify offset distance or [Through] : (/ (getdist "First point: ") 12.5)
First point: pick first point as you would in DIST
Specify second point: again, pick second point
3560.6131
Select object to offset or : execute the command
Now, isn't this great? We can simply use AutoLISP to ask us to input a distance on the screen, divide that distance with 12.5 and return the result to OFFSET. The expression (getdist "First point: ") simply executes the function GETDIST and returns the distance between two points picked on the screen to the division, which in turn divides the distance with 12.5.
A programming language wouldn't be a programming language without the ability to use variables, and of course, AutoLISP is no different in that aspect. Variables are simply placeholders in memory that can store a value of some kind. Variables are referenced by a name of your own choice.
Let's say a certain calculation appears frequently and we need to use the result in recurrent OFFSET commands. The result may have 12 decimals, so trying to remember the exact number, yet alone write it each time would be tedious indeed. All we need to do is to store the result in a variable and then use the name of that variable each time the number is used. The SETQ function in AutoLISP assigns a value to a variable:
Command: (setq myvar (/ 3521.0 27))
130.4074
Even though the result has an infinite number of decimals only a few are shown on screen, but don't be fooled - AutoLISP stores up to 16 decimals internally. Now that the result is stored in variable myvar, how to get it back? As it can be seen, AutoCAD communicates directly with AutoLISP and there are a few characters that tell AutoCAD to recognize the things written at the command prompt as AutoLISP expressions. A left paranthesis is one of the characters - when AutoCAD sees something written that starts with a left paranthesis it knows it has to get in touch with its inner AutoLISP. Another character is the exclamation mark ! - this tells AutoLISP that AutoCAD needs to retrieve a value from a variable.
Given that myvar is now a variable holding a value we can simply invoke the OFFSET command and retrieve its value by preceeding the variable name with an exclamation mark:
Command: OFFSET
Specify offset distance or [Through] : !myvar
130.4074
Select object to offset or : execute the command
Variables exist as long as the drawing remains open, and values they hold exist until they are replaced by new values - one by one. This means that you can store values for the duration of a drawing session. To reassign a value to an existing variable simply use SETQ in the above manner.
There are no limits to variable names, except that the characters ( ) . ' " and ; (left/right parenthesis, period, apostrophe, quote and semicolon) can't be used. Also, a variable name cannot consist of numerical characters only. Of course, names of built-in functions and constants are reserved and should never be used as variable names. Only memory sets the limits of the number of variables.
Before ending this chapter let's make a few notes on datatypes. For obvious reasons, different types of data varies in size. The computer doesn't like to waste memory, so each datatype has a predefined size in memory when it is stored. AutoLISP doesn't put restraints on the user when using variables, unlike other languages where you have to declare a variable in order to reserve space in memory before it can be used. Variables in AutoLISP are declared dynamically - i.e. AutoLISP determines how much space to reserve when reading the value it has to store.
Functions, on the other hand, expect that arguments passed to them have the correct datatypes, and they return a certain datatype themselves. However, some functions like the arithmetical ones can handle more datatypes and, what's more, they return different datatypes depending on the input. This is the reason that the calculations above contains at least one real number, for example (setq myvar (/ 3521.0 27)). If both arguments had been integers the division would have output an integer and you would have lost the decimals. If just one of the arguments is a real number, the result is a real number too.
This chapter was written to get you quickly started with AutoLISP without going into serious discussions about syntax, function evaluation or how to build functions yourself.
To summarize this chapter you learned how to write AutoLISP expressions and how to evaluate them in AutoCAD. You learned that functions in AutoLISP are written within one set of parantheses, that the function name is the first, leftmost part within the parantheses and that arguments, if any, are written to the right of the function name. Functions can be nested because they, just like nested calculations, are evaluated "inside out" returning the result of the deepest nested function to the function at next level. You also learned that some functions in AutoLISP, like GETDIST, can act as AutoCAD commands by asking the user for certain inputs. Finally you learned that AutoLISP stores values in variables, and that the function SETQ assigns a value to a variable.
Everything that was discussed in this chapter also applies when building large programs. You didn't learn anything that you won't use extensively if you intend to write AutoLISP applications, so in other words: you are off to a good start!
Part II will look at the syntax in AutoLISP in a more formal way. Evaluation of an AutoLISP expression is closely related to the function syntax, and those two topics together with notational (or lexical, if you like) syntax are covered next.
http://intervision.hjem.wanadoo.dk/intro1.htm
Part I very briefly touched on the history of AutoLISP and made a quick introduction by using it in AutoCAD with some examples explained. Part II will do a more formal introduction to the syntax and how AutoLISP expressions are build.
Function syntax and evaluation
LISP is sometimes referred to as "Lots of Irritating and Silly Parantheses", and it's not all wrong. There are a lot of parantheses and they can be irritating. But once you get started you will learn that they are not all that silly.
There are two main rules to remember when dealing with AutoLISP, one syntactical - the other functional:
Every AutoLISP expression is enclosed within a set of parantheses. The left paranthesis signals the start of the expression and the right signals the end.
Every AutoLISP expression returns a value.
Unlike Basic, Pascal or C where expressions (or subroutines/functions/procedures) can be executables only - without returning a value, there is only one kind of expression in AutoLISP and that is the one that returns a value. It is up to you, the programmer, to know when to use the returned values and when not to use them.
The generic syntax of an AutoLISP expression is like this:
(function arg1 arg2 arg3...)
Each function is enclosed by a pair of parentheses; the rightmost part within the parantheses is the function name and everything to the right is arguments to that function. Arguments are datatype specific (with a few exceptions) and can be anything that represents or evaluates to the datatype in question.
This construction has alot to do with the list-processing capabilities in lisp as you will experience later when we build a user defined function, but don't confuse it with lists yet. For now just get used to the fact that this is how a function appears.
A simpel expression in AutoLISP can look like this:
(polar myPoint 0.7854 45.5)
This built-in function returns a point that lies at an angle of 0.7854 radians and in a distance of 45.5 units from the point stored in variable myPoint. It follows the syntax described above - function name to the left, arguments to the right and enclosed by a set of parantheses. More commonly you will see expressions looking like this:
(setq myvar (polar myPoint 0.7854 45.5))
This is actually two functions, a SETQ function and a POLAR function. Each function is enclosed by its own set of parantheses. If the expression is written with an indented notation as is often used in AutoLISP, the parantheses become clearer:
(setq myvar
(polar myPoint 0.7854 45.5)
)
Any function in AutoLISP returns a value. If function A is calling another function B then function B will return a value to function A. Popular speaking you can say that a function is replaced by a value after execution, and that is important to understand in order to nest functions. Nested functions are simply functions used a arguments - as the example above shows.
The POLAR function will be executed first and then return the result as an argument to SETQ (SETQ is the generic assignment function in AutoLISP - it is used to assign a value to a variable). Nesting is allowed because every statement returns a value. As a statement is evaluated from left to right, the interpreter will evaluate each item. If the items are part of a nested function, the values are passed to the function when all arguments to that function have been evaluated. Popular speaking you can say that statements are evaluated "inside out" but in reality they are evaluated from left to right. When constructing a statement it is sometimes easier to think of it as a number of levels to be executed, where the deepest levels are evaluated first - just like we did in school when defining a sequence of math expressions with parantheses.
Below is a stylized diagram of parts involved in the expression shown above:
start and name of main function
1st argument to main function
start and name of nested function
1st argument to nested function
2nd argument to nested function
3rd argument to nested function
end of nested function
end of main function
return value of nested function becomes 2nd argument to main function SETQ
(setq
myvar
(polar
myPoint
0.7854
45.5
)
)
In the remainder of this text the term expression or statement is used to describe anything within a pair of parentheses, whether it be pieces of executable code or not and whether it consists of nested functions or not.
When a series of separate expressions are executed their return values are "overridden" by each other and only the last result is returned, but SETQ or one of the other assigment functions can at any time be used to grab a value by assigning it to a variable.
Consider the following series of expressions:
(setq var1 (* 5 110)) ; assign 5*110=550 to variable var1
(setq var2 (+ 20 200)) ; assign 20+200=220 to variable var2
(/ var1 var2)
During execution these expressions return a value each, but only the return value of the last executed expression remains available, for example, to a function that called the sequence (visually the value will be printed to the screen). Of course, during execution the return values from the first two functions were stored into variables with SETQ and they can now be used for further processing.
Before moving on to learn how to put together code into user-defined functions and routines let's have a look at some important and helpful notation syntax in AutoLISP.
By the way, AutoLISP is a registrered trademark by Autodesk - it is the name of this language and is used throughout this text. VisualLISP is the registrered trademark name of a programming environment for AutoLISP - it is a product owned by Autodesk Inc. and is shipped with AutoCAD 2000 or later (though available for release 14.01 by special purchase).
Notational (lexical) syntax
AutoLISP source code and programs destined for interpretation (as opposed to compiled code which is also an option) are written in ASCII text and is as such handled by any editor that handles ASCII text. As for any programming language there are some notational rules that apply when writing the code.
The most important syntactical rules are the ones described above. Besides the sequence of the parts inside an expression it is imperative that parantheses are paired. Also, double quotes are used for string datatypes and it is equally important that double quotes are paired.
When entering code that lacks ending parantheses in AutoCAD they can usually be added by hand because the AutoCAD prompt will point out how many parantheses are missing. If double quotes aren't paired the only solution is to correct the problem and start over. When writing code in the VisualLISP environment it has different tools to locate such problems.
Spaces or tabs divide the different parts in an expression, but as long as there is at least one space or tab between the parts it doesn't matter how many spaces/tabs are used:
( setq myvar (/ 5 40.0) ) ;this silly example is just
;as valid as the functions above
In AutoLISP files linefeeds are not important either - they don't terminate an expression and you can use as many as you like. Only parantheses determine where an expression begins and where it ends.
The following characters terminate a symbol name or numeric constant:
( ) ' " ; [space] [end of line]
A semicolon in AutoLISP signals the start of a comment - as shown in the previous examples. Everything after the semicolon until the end of the line is regarded as a comment. Thus, the end-of-comment sign is the end of the line. Normally, if you want to expand comments for more than one line you have to start each line with at least one semicolon. There is one way of expanding comments over several lines, though - with the special two-character pairs ;| and |; (the character | has ascii code 124).
Some characters aren't allowed in symbol names. Otherwise symbol names can consist of any sequence of printable character, except that they can't consist of numeric characters only. The charcters not allowed are:
( ) . ' " ;
When using symbol names, take care that you don't use predefined names of functions, symbols and constants - in other words: don't use reserved names. A typical example is the name pi that in AutoLISP is a constant for .. you guessed it .. pi.
Notes: When writing AutoLISP in menus, a plus-sign has to end a line if the expression continues on the next line. Semicolon in menu files means Enter or CR - therefore it is not allowed to use semicolons as comments in menus.
When using VisualLISP different numbers of semicolons have different meanings, but they are still signalling start-of-comment.
Other notational and syntactical conventions are:
Symbol and function names are not case sensitive
Integer constants can begin with + or - (minus). These are optional.
Real constants consist of one or more digits, a decimal point (period) followed by one or more digits. Omitting digits in front of the decimal point produces an error. Real numbers can be in scientific notation with the letter e or E written in front of the exponent, e.g. 4.514E10 or 4.514e10.
Single quotes are commonly used instead of the QUOTE function.
Within quoted strings a backslash denotes a control character. As an example the sequence \" can be used to return a single double quote - this is used within strings where the string has to contain a double quote. Control characters are:
\\ the character \ (backslash)
\" the character " (double quote)
\e escape
\n newline character (take notes - this is a useful one)
\r return (CR character)
\t tab character
\nnn the character whose octal code is nnn
Part III will decribe how to get started on defining your own functions and, by that, starting to build your AutoLISP routines and programs.
http://intervision.hjem.wanadoo.dk/intro2.htm
In part II we looked at function syntax and evaluation as well as some notational syntax that is used when writing AutoLISP code. Part III will introduce you to the steps of piecing together a user-defined function.
Building a user-defined function
Programming languages has long since been procedural, i.e. made up by chunks of independant code that each accomplishes its own task, both by itself and by calling other chunks of code when needed. A simpel program can be written in a linear fashion executed from top to bottom, but more commonly you will write a series of functions that will interact with each other in order to accomplish a task. Just like any code make calls to built-in functions repeatedly, user-defined functions can be reused by your code instead of having to repeat the same code when needed.
To write a user-defined function in AutoLISP use DEFUN. The easiest way to explain how to get started is .. well, to get started. Fire up AutoCAD and VisualLISP or some text editor and let's write a function that returns a point relative to another point. The point returned by the function will lie in an angle of, say, 0.7854 radians and a distance of 45.5 units from the input point. The function will also put the returned point into the system variabel LASTPOINT so it can be accessed with @ in AutoCAD:
(defun myPolar (pt / myVar)
(setq myVar (polar pt 0.7854 45.5))
(setvar "LASTPOINT" myVAR)
)
You will immediately notice that all expressions that make up the function body (all two of'em) is enclosed by the parantheses of the DEFUN statement. This is a because of LISP's list-processing features - everything that starts with a left and ends with a right paranthesis is regarded a list, and in LISP there are only two fundamental parts: atoms and lists. Atoms are the components of a list and a list is a series or collection of atoms that has to be processed. Within any particular list atoms can be lists themselves, but broken down you are left with the single components and those are what is called atoms.
If a list starts with a function name it is executed by that function. If a list starts with an atom that is not representing a function name it is regarded as a list of data. This can naturally be tricky stuff to swallow at this time and it doesn't really matter if you get it right now. I recommend that you, after learning what can be learned from this little primer, get familiar with the datatypes in AutoLISP - an introduction to datatypes can be found here.
The important thing is that a DEFUN is regarded as a function as any other function, and the body that carries out the job is nested into the DEFUN function, i.e. betweeen the open and closing parantheses that defines DEFUN. Now, on with the DEFUN.
A DEFUN statement starts with the name DEFUN followed by the function name that will be used when calling the function. Next is a special list that describes any arguments used in the function, followed by a slash character and local variable names used in the function. This slash character is not a division function in this case but merely separates arguments and local variables - more about local variables later.
Following the list of arguments and variables is one or more expressions that does the actual job. You can call this part the function body, if you want. All expressions are evaluated from top to bottom. The last part of the user-defined function is the closing paranthesis of the DEFUN statement.
Let's add some comments to this function:
(defun myPolar (pt / myVar) ; function name is myPolar
; function takes one argument, named pt
; function has one local variable, named myVar
(setq myVar (polar pt 0.7854 45.5)) ; calculate the point relative to pt and store
; the result in variable myVar
(setvar "LASTPOINT" myVAR) ; store the value of myVar in sysvar LASTPOINT
) ; end of defun
How is this function used and how does it return a value? As you learned in part II any function returns a value. In a DEFUN all expressions within the function body returns a value and the value returned by the last expression executed is the value that is returned by the DEFUN statement. This means that any code that calls this function with a valid argument will get access to the return value:
(setq newPoint (myPolar aPoint))
This call invokes myPolar with the argument aPoint. Given that aPoint contains a valid point datatype it is processed and the last expression in myPolar will return the point stored in system variable LASTPOINT. This is the value returned to the calling function which in turn stores the return value in a new variable, newPoint. You now have a point in newPoint that is placed in relation to aPoint exactly as calculated by the function myPolar.
A function doesn't need to return a value - it can merely execute in order to take some kind of action. After calculating the new point you can have the function draw a point in AutoCAD without ever worrying about a return value:
(defun myPolar (pt / myVar)
(setq myVar (polar pt 0.7854 45.5))
(setvar "LASTPOINT" myVAR)
(command "POINT" myVar)
)
The last statement is now a COMMAND function that enters the current AutoCAD drawing and simply draws a point. COMMAND is used to invoke any AutoCAD command programmatically in AutoLISP. It takes as arguments the command name followed by any sequence that is expected by that particular command in AutoCAD. If you wish to draw a line between aPoint and the new point you simply follow the sequence in the LINE command:
(setq newPoint (myPolar aPoint))
(command "LINE" aPoint newPoint "")
As you know the LINE command assumes that you want to draw more lines and continues to ask for next endpoint. To terminate the command in AutoCAD you hit enter, return, space or escape. To terminate the command in AutoLISP you insert an empty string to simulate Enter being hit. That is why the last argument in the above COMMAND function is an empty string ("").
Now you can have a main function that, for example, gets a point picked in a drawing, invokes myPolar in order to calculate the new point and then draws a line between the point that is picked and the new point:
(defun myPolar (pt / myVar)
(setq myVar (polar pt 0.7854 45.5))
(setvar "LASTPOINT" myVAR)
)
(defun C:Relative ()
(setq aPoint (getpoint "Line relative from point: "))
(setq newPoint (myPolar aPoint))
(command "LINE" aPoint newPoint "")
)
These two functions can be written to a lisp file, loaded into AutoCAD and executed like any other command (more about loading a function later). Notice that the name of the main function is preceded by a C and a colon. Whenever AutoLISP loads such a function it is made accessible by AutoCAD to be used as a built-in command. There is no other difference in the DEFUN statement than preceding the name with "C:".
The GETPOINT function that got slipped in through the backdoor here is a function that asks the user to pick a point on the screen. It interacts with AutoCAD by printing the string "Line relative from point:" at the command prompt and waits for the user to pick a point on the screen. The picked point is returned by GETPOINT and in this case grabbed by a variable, named aPoint.
When invoked in AutoCAD it acts like this:
Command: relative
Line relative from point: [pick a point to continue]
nil
Upon picking a point it draws the line. Notice that "nil" got written to the screen. This is because all expressions return a value and COMMAND always returns nil. To avoid that the last value is written to the screen use a PRINC statement without arguments as the last expression in your code. PRINC issued without an argument returns a null symbol which, of course, is invisible on screen. This technique is known as "silent exit" and is used whenever terminating a routine that has no point in returning a value to the user:
(defun C:Relative ()
(setq aPoint (getpoint "Line relative from point: "))
(setq newPoint (myPolar aPoint))
(command "LINE" aPoint newPoint "")
(princ)
)
Let's go through some steps that make the code available, not only to the current drawing but in whatever drawing you wish. First save your code as a separate text file with the extension .lsp - take care that it is stored as an ASCII file, i.e. an unformatted text file. Place the file in one of AutoCAD's search paths. If you are not clear on your search paths then open the Options dialog, click on the Files tab and expand the Support File Search Path item. You can have lisp files whereever you want, but if they are not placed in a search path you will have to specify the whole path in the next procedure.
In any drawing type the following expression at the AutoCAD command prompt:
(load "relative")
LOAD is an AutoLISP function like any other - it takes one argument, a file name with or without extension, reads the file and attempts to load any code found. If succesfull it will return the value of the last expression in the file - in this case it will return "C:RELATIVE" because the last expression is the DEFUN of that name. If you are using VisualLISP you can still save the file and use the statement above, or you can choose Tools->Load text in Editor or simply click the load button in the toolbar.
All the functions in Relative.lsp is now available whether they are defined as commands or not. Because each drawing has its own environment in memory the lisp functions are normally only available to the drawing that was active upon loading of the lisp file. Some techniques exist to make functions available to all drawing but that lies beyond the scope of this text.
Loading and executing your newly defined command concludes this chapter and this little AutoLISP primer. That wasn't too hard, was it? It is my hope that you will continue your journey into the world of AutoLISP. Of course, if you are new to any programming it is kinda rough getting started, no matter how easy people tell you it is. I've heard people who are programming in LISP and other languages refer to AutoLISP as a toy programming language. Yes, it is a kind of macro language in nature and yes, it is a very small subset of Common Lisp, but it is nevertheless a fully grown programming language that is merely designed for a very specific purpose - and very well designed for that purpose it is too.
There will probably be many terms and topics that will be harder to understand than others. In my point of view it is always easier to wait with those topics and go on with the ones that you feel comfortable with, instead of giving up trying to understand something that will eventually become clearer when you gain some more experience.
Start out with a simple problem that utilizes the user input functions and the COMMAND functions as much as possible - there's no need to start on complicated parametric code when AutoCAD already can do the job for you. Get comfortable with the syntax, the different datatypes, the assignment mechanisms and the interaction between AutoLISP and AutoCAD before anything else and you will learn that you can get pretty far and at the same time pick up on the more tricky techniques as you go along.
TOP
By the way, you may have noticed that more languages have been introduced to the AutoCAD product family, and you may also have heard of some languages being introduced and later becoming obsolete. AutoCAD is like any other software product - it has to keep up with demands but also with technology. From time to time it is being discussed whether or not a language like AutoLISP will ever loose its support by its creators. Although it's been constantly improved over time it once seemed to be standing pretty still and especially with the withdrawals of AutoCAD from all other platforms than Windows and the implementation of the Windows "standard" programming environment Visual Basic it became an even more valid discussion if AutoLISP was to become obsolete.
I have an AutoLISP reference manual from release 11 back in 1990 in which Autodesk states that they are committed to long-term support for AutoLISP and it does seem that they proved this statement by at least "doubling" the features of AutoLISP with release 2000. It got totally rewritten, it got a brand new editor with debugging and many other features built in (a product already in the market by another software company from whom it was bought, but nevertheless...) and it got total access to the object model which features an almost complete set of hooks into the Visual Basic environment. My personal conclusion to all this is that Autodesk keeps their promise of long-term commitment, but noone can tell the future. So far nothing indicates that AutoLISP is falling off the face of the earth, so if you are worried that your efforts in learning and using this language will be wasted I can only say: go for it!
http://intervision.hjem.wanadoo.dk/intro3.htm
AutoCAD, AutoLISP and VisualLISP are registered trademarks by Autodesk, Inc. In case of listing, describing or mentioning another brand or product it is most probably also a trademark or registered trademark by Autodesk, Inc. Other brand and product names mentioned or described in these pages are trademarks or registered trademarks of their respective companies.
Share with your friends: |