AutoLISP: The Complete Guide — Chapter 6 / 16

Defining Functions

Up until now, we have been typing expressions directly into the command line. This is useful for testing, but to write real programs, you need to be able to group instructions together and reuse them. That is exactly what functions allow you to do.

Creating a function with defun

The defun function (define function) creates a new function:

(defun circle-area (radius)
  (* pi (expt radius 2))
)

Let's break down this definition:

  • defun: the keyword for defining a function
  • circle-area: the name of the function
  • (radius): the list of arguments (here, just one)
  • (* pi (expt radius 2)): the body of the function

To use this function:

(circle-area 5)    ; → 78.5398
(circle-area 10)   ; → 314.159

Defining and calling the circle-area function

Multiple arguments

A function can accept as many arguments as needed:

(defun box-volume (length width height)
  (* length width height)
)

(box-volume 10 5 3)  ; → 150

The return value

In AutoLISP, a function returns the value of its last expression. There is no return keyword:

(defun double (number)
  (* number 2)
)

(double 7)  ; → 14

If your function contains multiple expressions, the last one determines the return value:

(defun greet (name)
  (princ (strcat "Hello " name "!"))
  (terpri)   ; New line
  nil        ; Return nil to avoid unwanted echo
)

Local variables

By default, variables created with setq inside a function are global: they remain accessible after the function has finished executing. This can cause conflicts. To avoid this, declare your variables as local by listing them after a / in the argument list:

(defun rectangle-area (length width / area)
  (setq area (* length width))
  area
)

Here:

  • length and width are arguments
  • area (after the /) is a local variable: it only exists during the function's execution
(rectangle-area 10 5)  ; → 50
!area                   ; → nil (the local variable no longer exists)

Variable scope

Without the /, the area variable would remain accessible outside the function, which could interfere with other parts of your program.

Best practice: always declare your internal variables as local. The only variables that should be global are those you explicitly want to share between multiple functions.

Creating AutoCAD commands with c:

The most powerful feature of defun in AutoLISP is the ability to create new AutoCAD commands. Simply prefix the function name with c::

(defun c:hello ()
  (alert "Hello from my custom command!")
  (princ)
)

After executing this definition, you can type HELLO directly in the AutoCAD command line, just like any native command!

Message box displayed by the command

A few important points:

  • c: commands take no arguments (the argument list is empty ())
  • They can have local variables: (defun c:mycommand (/ variable1 variable2) ...)
  • The (princ) at the end prevents an unwanted return value from being displayed in the command line

Example: area calculation command

Let's create a command that asks the user for a circle's radius and displays the area:

(defun c:circle-area (/ radius area)
  (setq radius (getreal "\nEnter the circle radius: "))
  (setq area (* pi (expt radius 2)))
  (alert
    (strcat "The area of the circle with radius "
      (rtos radius 2 2)
      " is "
      (rtos area 2 2)
    )
  )
  (princ)
)

circle-area command in action

The getreal function displays a message and waits for the user to enter a real number. We will explore other user interaction functions later.

Writing code in a file

Typing long functions into the command line is not practical. In practice, you write your code in a text file with the .lsp extension and load it into AutoCAD.

Historically, AutoCAD included a built-in editor called VLIDE (Visual LISP IDE). This editor is now obsolete: its interface has not evolved since the 2000s and it no longer receives updates from Autodesk.

Since AutoCAD 2021, Autodesk recommends using Visual Studio Code (VS Code) with the official AutoCAD AutoLISP Extension. VS Code is a free, modern editor widely used by developers worldwide.

Installing VS Code for AutoLISP

  1. Download and install Visual Studio Code (note: this is different from Visual Studio, which is a full development environment)
  2. Install the AutoCAD AutoLISP Extension from the marketplace

AutoLISP syntax highlighting in VS Code

Why choose VS Code over VLIDE?

VLIDE already offers syntax highlighting, a debugger, and an AutoLISP console. But VS Code goes further:

  • Multiple cursors, advanced search, powerful keyboard shortcuts
  • Refactoring: variable and function renaming, and other automatic code transformations
  • Git integration for managing your program versions
  • AI support (GitHub Copilot, etc.) to help you write code

Tip: in AutoCAD, the VLISP command launches VS Code directly if the LISPSYS system variable is set to 1 (the default value since AutoCAD 2021). If you are still using VLIDE, set LISPSYS to 1 and restart AutoCAD.

Creating and saving a .lsp file

  1. In VS Code, create a new file with Ctrl+N
  2. Select the AutoLISP language (Ctrl+K then M)
  3. Write your functions
  4. Save the file with the .lsp extension (for example my-tools.lsp)

You can run your code directly from VS Code with Ctrl+F5, or load it manually into AutoCAD.

Loading the file in AutoCAD

In the AutoCAD command line, use the APPLOAD command or type:

(load "C:/path/to/my-tools.lsp")

All functions defined in the file become immediately available.

Tip: in AutoLISP file paths, use forward slashes / (not backslashes \), or double the backslashes \\.

Useful interaction functions

Here are the basic functions for interacting with the user:

;; Ask for an integer
(getint "\nEnter an integer: ")

;; Ask for a real number
(getreal "\nEnter a real number: ")

;; Ask for a string
(getstring "\nEnter your name: ")
(getstring T "\nEnter a sentence: ")  ; T allows spaces

;; Ask for a point (click in the drawing)
(getpoint "\nClick a point: ")

;; Ask for a distance
(getdist "\nSpecify the distance: ")

Complete example: parametric rectangle

(defun c:rect-info (/ point1 length width area perimeter)
  ;; Ask for dimensions
  (setq length (getreal "\nRectangle length: "))
  (setq width (getreal "\nRectangle width: "))

  ;; Calculate
  (setq area (* length width))
  (setq perimeter (* 2 (+ length width)))

  ;; Display results
  (alert
    (strcat
      "Rectangle " (rtos length 2 2) " x " (rtos width 2 2)
      "\n\nArea: " (rtos area 2 2)
      "\nPerimeter: " (rtos perimeter 2 2)
    )
  )
  (princ)
)

Summary

Concept Syntax
Define a function (defun name (args) body)
Local variables (defun name (args / locals) body)
Create an AutoCAD command (defun c:name (/ locals) body)
Recommended editor Visual Studio Code + AutoLISP extension
Run from VS Code Ctrl+F5
Load a file (load "path.lsp")
Ask for a number (getreal "message")
Ask for a point (getpoint "message")
Ask for a string (getstring "message")

In the next chapter, we will learn about control structures: how to make decisions with if and cond, and how to repeat actions with while and repeat.


Helping hand Need an AutoCAD (AutoLISP, ObjectARX, .NET, VBA) development? Contact me for a free quote.