In this series, I will talk to you about LISP programming in BricsCAD. This blog post will walk you through what you need to know to become a very productive programmer. In the first two or three posts, I will introduce you to terminology, syntax, and data types.
What is LISP Programming?
LISP (LISt Processing) in BricsCAD is an easy-to-learn programming language for the non-programmer. Programming is simply intelligently obtaining, using and/or reusing data.
Terminology and Data Types
These are a few common terms that will get you going in the right direction. You will note that a flow somewhat develops as we work our way down the list of terms. Keep in mind that all of this is very logical. There are no tricks. It is logical. Things work the same way every single time. It is logical. Always the same. Did I mention it is logical?
List Anything contained within a set of parenthesis ( )
Atom The individual items within a list
Function LISP’s “commands”, typically the first atom within a list
Argument The atoms that follow the function name. These are the data the function you are using needs in order to complete its task.
Expression A list that involves a function, and possibly, arguments
Integers Whole numbers, no decimal point
Reals Floating point numbers, always has a decimal point
Strings Text, always contained within a set of quotation marks: “Like this”
Lists It may not seem logical that we are using the same term twice, but it will be explained!
Prep Work for Practicing
Before practicing the use of functions at the command prompt, it is advantageous to turn off the Dynamic Input setting. Toggle it off (turn it dark) using the status bar in BricsCAD:
Also — it is a good idea to make your command prompt area show a few lines “taller” than usual — maybe 8 or 10 lines. To do his hover you mouse over the top of the Command line edge until a double arrow appears and click and drag to change the height of the Command line:
(functionname argument1 argument2 …)
The basic type of lists we will be working with can be referred to as expressions. An expression is a list that always takes on the above format. The first element (or atom) of an expression is always a function. Additional atoms in the list are referred to as arguments. Arguments are the tools or “things” a function needs to work properly. Arguments that are passed to a function, for our purposes, must be of one of 4 data types: an integer, a real, a string, or a list.
Math Related Functions
The following simple functions help us to understand how the syntax and the terms listed previously work together. Simple, short functions can be typed in directly into the Command line. This makes testing and troubleshooting (and initial learning!!) very convenient.
Feel free to type some of what I am introducing, right as we go along…
(+ num num …)
The addition function (+) takes any number of numeric arguments and adds them together and returns the sum.
(- num num …)
The subtraction function (-) takes any number of numeric arguments. The first argument can be considered the base number. All additional arguments are successively subtracted from that base argument.
(* num num …)
The multiply function (*) takes any number of numeric arguments and multiplies them together and returns the product.
(/ num num …)
The divide function (/) takes any number of numeric arguments. The first argument can be considered the base number. The base number is successively divided by each of the additional arguments.
To use a negative number simply place a minus sign in front of it. (Optionally, positive numbers may have a plus placed in front of them — but it is extremely rare). -3.75, -42, +6.953
Real numbers less than 1 and greater than -1 must have a zero (0) in front of the decimal point. 125, 0.5, -0.67
If all the arguments passed to a math function are integers, an integer will be returned. If at least one of the arguments is a real number, a real number is returned.
Real numbers are stored accurately to more than 15 decimal places but are “returned” (displayed at the command prompt) to no more than 15 significant digits.
Examples of math functions entered into the Command line:
Being able to perform all these math functions is great, but not very useful unless we store the values. The (setq) function allows us to store a value or data, in a variable or symbol.
(setq sym value)
The setq function requires an even number of arguments. The odd numbered arguments are the symbols and the even numbered arguments are the values to be stored in that symbol. For learning’s and simplicity’s sake, we will use (setq) with just two arguments; the symbol and the value it will hold. The symbol can be most any typed character, but not just a number. (A number already holds a value!) Some other characters are invalid also, such as +, -, *, /, (, ), or any function name already defined in LISP… these symbols already have meanings or value in LISP. Examples of valid symbols:
A B X PT PT1 PT2 MIDPT CNTRPT CLR1 FIRST-NAME DWGNUM
We can use the (setq) function to store some of the types of data we referred to earlier:
(setq A 1)
(setq B 2.5)
(setq C “BricsCAD LISP”)
returns “BricsCAD LISP”
(setq X 1.25 Y 6.375 Z 0.0)
(setq CPT 3.5 OPT “Diameter” RAD 4.0 )
The last two expressions above are a valid way of coding, but not often used. It can make troubleshooting, adding and/or deleting code somewhat confusing.
In the second to last example it appears that X and Y did not get “set”, and in the last example it appears that CPT and OPT did not get “set”. But between the two examples all 6 symbols did in fact get “set”. The (setq) function returns the results of evaluating the last argument passed to it.
The preceding sequence of code could be referred to as “hard coding”. The values that the symbols are holding onto are not allowed to vary (X is absolutely “1”, never anything else!). They are always going to be exactly as shown — the symbol is holding onto whatever value the programmer typed as the second argument. There is no allowance for input from the user.
LISP has the functionality to allow expressions to be nested within other expressions. To start off, the functions that we will nest within the (setq) function will be functions that allow us to get certain data types from the users of our programs.
First, we will look at a few data type gathering functions, and then we will nest them within a (setq) to store their values.
Getting Specific Data — By Data TYPE
Earlier we mentioned that LISP relies upon using data of specific types appropriately. We mentioned 4 specific types of data: Integers, Reals, Strings, and Lists. LISP provides functions to specifically allow the programmer, to allow the user of a program, to enter values that can differ when necessary.
Allows the user to input an integer value.
Optionally allows a string argument to be used as a prompt. Returns the input value as an integer.
Allows the user to input a real or floating-point value.
Optionally allows a string argument to be used as a prompt. Returns the input value as a real number.
(getstring flag str)
Allows the user to input an integer value.
Optionally allows a string argument to be used as a prompt. Also allows an optional argument, that if “has value” allows spaces to be included in the input string. Returns the input string as a string.
(getpoint pt str)
Allows the user to input a point value.
Optionally allows a string argument to be used as a prompt. Also, optionally allows a “starting” point argument. Returns the input point as a list.
This one is just a little tricky to interpret, but once understood it is indeed logical!
That last sentence is the key to understanding previous discussion on data types. We mentioned that there are 4 main types of data and it is obvious that the first 3 of these functions handle the first 3 data types that we have mentioned. The last function is (getpoint) — and there is no data type called “point”. We did mention that there is a data type called a “list”. To clarify… We mentioned that a list is anything contained within a set of parentheses. We also mentioned that an expression is a specific type of list — one that has a function as the first atom of the list, and any additional atoms are called arguments. The (getpoint) function returns “just” a list — not an expression like all the lists have been that we have been dealing with up to this point. The list that this function returns is comprised of three atoms. All three atoms are of the “real” data type. The first atom is the X value of the point, the second is the Y value, and the third is the Z. So, (getpoint) returns a list, and it is often referred to specifically as a “point list”. Understanding the logic behind this paragraph is key to you beginning to understand how the LISP language works!
Using the Stored Data
Once data has been gathered from the user, it is common to use that data to add objects to a drawing or modify existing objects in a drawing. For now, we will use stored data to draw some objects.
The (command) function is one way a programmer can add or modify objects in a drawing.
(command string argument argument …)
The first argument to the (command) will be a command name. It is always expressed as a string. The number of additional arguments and their data type depends upon what command is being used. This will become apparent in the next (and final for this time around!) section.
Put It All Together
We will go much deeper into each of these functions and concepts in future posts, but for now we will enter some lines of code at the command prompt to tie this all together. Type these lines of code directly at the command prompt. If something goes wrong, for now, just hit the escape key and retype the line of code.
(setq CPT (getpoint “Select a center point: “)) (setq RAD (getreal “Enter a radius: “)) (setq OFF (getreal “Enter an offset value: “)) (setq NEWRAD (+ RAD OFF)) (command “circle” CPT RAD) (command “circle” CPT NEWRAD)
Above, we have the makings of a program! In the next post we will learn how to store these lines of code in a text file so we no longer need to type them out at the Command line every time we want to draw an offset circle. (And, of course, we will take our new-found knowledge even deeper than just drawing a couple of circles!)