PREABLE:I want to start a series of tutorials/discussions about basic AutoLisp programming. If you are new to AutoLisp and find problems or lack of information, please ask. If you are an experienced AutoLisp programmer and you find problems or errors, please speak up (and help those who ask questions).
Thank you - John
AutoLisp Tutorial
Text editorAutoLisp is typed in plain text so Notepad is used--not MS Word. There is also a built-in AutoLisp editor called the VLIDE.
There are also many other third-party text editors which can be used. Please start a new thread to ask other peoples opinions about which is best.
File typeFile types are typically .lsp.
File organizationA good folder structure is key to keeping yourself organized and your files backed up for safe keeping.
projects
|
+---doc
|
o---tools
| |
| +---ProjectOne
| | +---doc
| | |
| | +---src
| |
| +---ProjectTwo
| | +---doc
| | |
| | +---src
New project templateWe can create a batch script to prompt us for a project name and create the folders and files quickly. We will update this script throughout this tutorial.
Below is a simple batch script to ask for a project name and create a few folders and files to get started. Create a new text file in a project folder and paste the below code into it. Save the document as "New-AutoLisp-Project.bat". Double-click the batch script when you need a new project to work on.
@echo off
set /P prjName="What is the name of the project (No spaces)?: "
:mkdir
if exist %prjName%\nul goto FolderExists
md %prjName%
md %prjName%\\doc
md %prjName%\\src
echo ;; File Last Updated: >> %prjName%\\src\\%prjName%.lsp
if not exist %prjName%\nul goto FolderNotMade
echo Made folder %prjName%
goto end
:FolderExists
echo %prjName% already exists
goto end
:FolderNotMade
echo %prjName% could not be made
:end
pause
File backup proceduresYou can use a simple right-click-->archive process to keep regular backups. When things go wrong you can simply unzip the archive and your files will be restored back to that point.
AutoLisp BasicsFunction definitionWe define a function by giving it a proper name. A common trap most people fall into is to shorten, or abbreviate, a function name. For example Square Root is a common mathematical task and a simple function to write. Some people fall into a trap of shortening the name to `SqRt' or something of that like but, if you keep the name `SquareRoot' there will never be any question as to what that function does.
PLEASE NOTE: This may seem like a bad example--because you may already know that there is a built-in AutoLisp function called SQRT--but I would ask that you humor me while I use this as a introduction into other aspects of this tutorial.
To define a function we use this syntax:
(defun <NAME> As you can see the `defun' part is a function for DEfingning a FUNction name.
A major pitfall of the short/abbreviated naming comes into play later when you need a SquareRoot function but forgot that you built one already. You proceed to create another but call it `SquareRt' this time; now you have two functions that do the same thing. This isn't necessarily a problem except that you have two versions of the same thing but what happens if they do different things?
Accessing functionsTo call--accesss--a function we simply call it like we would any other AutoLisp function (-i.e. we wrap it in parens).
(SquareRoot <NUMBER>)Argument passingAs you can see the SquareRoot function we will build needs a number to preform that operation on. This is called an argument. To define a function that needs/has an argument we simply enclose that/those argument names in parens.
(defun SquareRoot ( number )We would call our program like this:
(SquareRoot 25)That argument (25 in this case) is like a variable (called NUMBER) and we can use/access that variable throughout our program.
Variable declarationTo create (declare) a variable we use the SETQ function.
Example (create a variable "a" to hold a number "1"):
(setq a 1)Accessing VariablesTo access that variable, we just use it.
Example (pass the variable A to our SQUAREROOT function):
(SquareRoot a)
SquareRoot TutorialTo build our squareroot function we need some helper functions. I wont go into too much detail about the inner workings of the function and it's helpers. Instead I will focus more on the structure of the example.
Here are all the pieces necessary to build a SquareRoot function for use in future programs.
(squareroot-iter 1.0 x)
)
(defun squareroot
-iter
(guess x
) (if (good
-enough? guess x
) guess
(squareroot-iter (improve guess x) x)
)
)
(defun good
-enough?
(guess x
) (< (abs (- (* guess guess
) x
)) 0.001) )
(average
(list guess
(/ x guess
))) )
)
)
We call/use the function like this:
(SquareRoot 25)You'll notice one problem; it's messy! You may be asking yourself what all the other stuff is and what it does. You may also be wondering how you will keep track of all these "useful/helper" functions are in a real program. That is the problem we will be focusing on for the first part of this tutorial.
To sum up this problem the only important function in the above is the "SquareRoot" function, all the other functions (squareroot-iter, good-enough?, improve, and average) is clutter. We can use a method called "Block-structure" to help clean this all up.
PLEASE NOTE: I've increased the indentation of the auxiliary functions to help with readability.
(defun SquareRoot
( x
/ squareroot
-iter good
-enough? improve average
) (defun squareroot
-iter
(guess x
) (if (good
-enough? guess x
) guess
(squareroot-iter (improve guess x) x)
)
)
(defun good
-enough?
(guess x
) (< (abs (- (* guess guess
) x
)) 0.001) )
(average
(list guess
(/ x guess
))) )
)
)
(squareroot-iter 1.0 x)
)
We can further optimize the block-structure method of our cleanup effort by understanding that passing the variable X around to the different helper functions is unnecessary.
(defun SquareRoot
( x
/ squareroot
-iter good
-enough? improve average
) (defun squareroot
-iter
(guess
) guess
(squareroot-iter (improve guess))
)
)
(defun good
-enough?
(guess
) (< (abs (- (* guess guess
) x
)) 0.001) )
(average
(list guess
(/ x guess
))) )
)
)
(squareroot-iter 1.0)
)
Each helper function which needs/uses X can still access it; this is called "lexical scope".