Author Topic: Tutorial 1 : AutoLisp Basics : Building Blocks  (Read 3824 times)

0 Members and 1 Guest are viewing this topic.

JohnK

  • Administrator
  • Seagull
  • Posts: 10637
Tutorial 1 : AutoLisp Basics : Building Blocks
« on: January 21, 2020, 01:20:21 PM »
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 editor
AutoLisp 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 type
File types are typically .lsp.

File organization
A good folder structure is key to keeping yourself organized and your files backed up for safe keeping.

Code: [Select]
        projects
        |
        +---doc
        |
        o---tools
        |       |
        |       +---ProjectOne
        |       |   +---doc
        |       |   |
        |       |   +---src
        |       |
        |       +---ProjectTwo
        |       |   +---doc
        |       |   |
        |       |   +---src

New project template
We 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.

Code - Bash: [Select]
  1. @echo off
  2.  
  3. set /P prjName="What is the name of the project (No spaces)?: "
  4.  
  5. :mkdir
  6. if exist %prjName%\nul goto FolderExists
  7. md %prjName%
  8. md %prjName%\\doc
  9. md %prjName%\\src
  10. echo ;; File Last Updated: >> %prjName%\\src\\%prjName%.lsp
  11. if not exist %prjName%\nul goto FolderNotMade
  12. echo Made folder %prjName%
  13. goto end
  14.  
  15. :FolderExists
  16. echo %prjName% already exists
  17. goto end
  18.  
  19. :FolderNotMade
  20. echo %prjName% could not be made
  21.  
  22. :end
  23. pause

File backup procedures
You 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 Basics
Function definition
We 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 functions
To 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 passing
As 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 declaration
To create (declare) a variable we use the SETQ function.

Example (create a variable "a" to hold a number "1"):
(setq a 1)

Accessing Variables
To access that variable, we just use it.

Example (pass the variable A to our SQUAREROOT function):
(SquareRoot a)


SquareRoot Tutorial
To 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.
 
Code - Auto/Visual Lisp: [Select]
  1. (defun SquareRoot ( x )
  2.   (squareroot-iter 1.0 x)
  3.   )
  4.  
  5. (defun squareroot-iter (guess x)
  6.   (if (good-enough? guess x)
  7.       guess
  8.       (squareroot-iter (improve guess x) x)
  9.       )
  10.   )
  11.  
  12. (defun good-enough? (guess x)
  13.   (< (abs (- (* guess guess) x)) 0.001)
  14.   )
  15.  
  16. (defun improve (guess x)
  17.   (average (list guess (/ x guess)))
  18.   )
  19.  
  20. (defun average (args)
  21.   (if args
  22.     (/ (apply '+ args)
  23.        (length args))
  24.     )
  25.   )

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.

Code - Auto/Visual Lisp: [Select]
  1. (defun SquareRoot ( x / squareroot-iter good-enough? improve average )
  2.         (defun squareroot-iter (guess x)
  3.           (if (good-enough? guess x)
  4.               guess
  5.               (squareroot-iter (improve guess x) x)
  6.               )
  7.           )
  8.        
  9.         (defun good-enough? (guess x)
  10.           (< (abs (- (* guess guess) x)) 0.001)
  11.           )
  12.        
  13.         (defun improve (guess x)
  14.           (average (list guess (/ x guess)))
  15.           )
  16.        
  17.         (defun average (args)
  18.           (if args
  19.             (/ (apply '+ args)
  20.                (length args))
  21.             )
  22.           )
  23.   (squareroot-iter 1.0 x)
  24.   )


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.

Code - Auto/Visual Lisp: [Select]
  1. (defun SquareRoot ( x / squareroot-iter good-enough? improve average )
  2.         (defun squareroot-iter (guess)
  3.           (if (good-enough? guess)
  4.               guess
  5.               (squareroot-iter (improve guess))
  6.               )
  7.           )
  8.        
  9.         (defun good-enough? (guess)
  10.           (< (abs (- (* guess guess) x)) 0.001)
  11.           )
  12.        
  13.         (defun improve (guess)
  14.           (average (list guess (/ x guess)))
  15.           )
  16.        
  17.         (defun average (args)
  18.           (if args
  19.             (/ (apply '+ args)
  20.                (length args))
  21.             )
  22.           )
  23.   (squareroot-iter 1.0)
  24.   )

Each helper function which needs/uses X can still access it; this is called "lexical scope".
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8698
  • AKA Daniel
Re: Tutorial 1 : AutoLisp Basics : Building Blocks
« Reply #1 on: January 22, 2020, 03:52:37 AM »
good-enough?, sorry

JohnK

  • Administrator
  • Seagull
  • Posts: 10637
Re: Tutorial 1 : AutoLisp Basics : Building Blocks
« Reply #2 on: January 22, 2020, 09:59:43 AM »
At first I thought you were commenting on my tutorial, then I remembered that was a function name.

The SquareRoot code was actually some Scheme code I found in a "junk-drawer-file" I had kept when I was writing lisp (it was probably for an assignment or just notes). When I got to writing the AutoLisp Basics part of the tutorial, that function was staring back at me so I went with it.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Tutorial 1 : AutoLisp Basics : Building Blocks
« Reply #3 on: January 22, 2020, 03:08:27 PM »
good-enough?, sorry
Thats definitely good enough for someone like me who is not familiar with autolisp.
I could actually  follow what the example was doing by its function names.

Most autolisp I see looks like this to me
Code: [Select]
(defun (a d i / d gg)
  (cc y h)
  (ggggt o  p)
)

JohnK

  • Administrator
  • Seagull
  • Posts: 10637
Re: Tutorial 1 : AutoLisp Basics : Building Blocks
« Reply #4 on: January 22, 2020, 03:20:57 PM »
(defun foo, (defun bar, (defun foobar mostly make me want to kick a bunny.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

ronjonp

  • Needs a day job
  • Posts: 7529
Re: Tutorial 1 : AutoLisp Basics : Building Blocks
« Reply #5 on: January 22, 2020, 03:25:28 PM »
(defun foo, (defun bar, (defun foobar mostly make me want to kick a bunny.
Does this make you want to hug a leopard? :evil:
Code: [Select]
raboof nufed( ,rab nufed( ,oof nufed(

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

JohnK

  • Administrator
  • Seagull
  • Posts: 10637
Re: Tutorial 1 : AutoLisp Basics : Building Blocks
« Reply #6 on: January 22, 2020, 03:31:07 PM »
No, but I did go cross-eyed there for a minute.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

HasanCAD

  • Swamp Rat
  • Posts: 1422
Re: Tutorial 1 : AutoLisp Basics : Building Blocks
« Reply #7 on: January 27, 2020, 07:42:47 AM »
+1