AutoLISP Lesson #5 - VARIABLES AutoLISP variables may be any of (4) four "types"; integers, reals, points, or strings. Variables in AutoLISP are automatically "typed" depending on the value they contain, so no "typing" of variables is required. The function SETQ will be used to create a variable. A variable will contain a nil value until some value is bound to it. If you reference a variable before you have assigned a value to it, you will receive nil as the result of the reference. (setq a 3) ;Integer variable Variable Naming Variables can be named anything you want providing the first character is alphabetic, and you don't use the reserved characters from lesson 2. Many AutoLISP programmers try to keep variable names to (6) six characters or less. This is due to the way variables are stored in AutoLISP. If a variable name is less than 6 characters AutoLISP only requires (2) two nodes to store the value. If you make the variable name longer than (6) six characters, AutoLISP stores the value in one node and stores a pointer to the name in the other node. The name itself is stored in memory taken from the heap for string storage. Heap space is limited and that is why some programmers try to keep variable names short. Two things have happened that makes this rule not so carved in stone as it used to be. The advent of virtual memory and learning how to program cleanly has done much to solve the problem of running out of memory. I can't do much about the amount of memory in your computer or the amount of memory AutoCAD needs, but I can show you how not to run out of memory by programming in a clean manner. Naming a variable is not like naming the family pet, you can't choose a name cause it's cute or it's what the variable looks like. You need to choose names based on what it is the variable holds. You must look at the variable and its name as being the same thing. If you can't tell what the variable is, maybe you don't need the variable anyway. If a variable holds the point for a line, state that in the variable name. First tell which line, and then tell which point. Variables can be named well or they can be named badly, it's all up to you. Good: Bad: The bad variable names have been made slightly more palatable by the use of comments to say what they are, but the good variable names are much more descriptive and require no comments. Anyone who has programmed for awhile knows comments rarely come easy, sometimes not at all. It is better to give your variables names, which do not need to be explained, so a missing comment later will not lead to confusion about what the variable is holding. Good: Bad: I have seen programmers go as far as giving many pages of comments to explain what each of their variables was supposed to hold. Having a decoder ring is no substitute for proper variable naming. If you give full variable names you will have less commenting and a easier time when hunting problems. Index variables If you are going to use short names for indexes be sure to tell what it is that you are indexing through. Good: Bad: An index variable is like any other variable and needs a proper name to be truly understood. Status variables Good: Status variables are not used extensively in AutoLISP programming, but if you use them, give them real names. Naming guidelines Variables should be named in a manner that also identifies their scope and / or type. GLOBAL variables gScrewList This identifies the variable as a list that is available to all the functions in your program. I am not a fan of putting the "_" character in variable names as a separator. I prefer the naming convention where you capitalize the first letter of each word or abbreviation in the variable name. CONSTANTS INPUT variables It will be easier to read your code and tell which variables are parameters if you identify them in the name. An "i" or "ip" may be prefixed to the name to identify them. Constants A constant should be used in place of magic numbers in your programs. A magic number is a numeric literal such as the value of PI, or a conversion factor that will not change throughout your program. If you use numbers that have no explanation other than the number itself, you and anyone who follows you, will have trouble figuring out what the number is for when it's time to change the program. Many times we will use constants to identify boundary conditions our program should not go above or below. In these cases a "_MAX" may be appended to the name to tell which end of the boundary we have hit. (setq LIST_MAX 10) The preceding code sets our maximum list number. It then says if we haven't reached that number to go ahead and do whatever it is we're up to. If I had wrote it using the 10 as the check value, we would have very little indication as to what I was checking for. Also if I used LIST_MAX somewhere else and I decide I need the maximum lists to be 12, I only have to change it in one place instead of looking all through my code to find everyplace I may have put 10. Variable usage Scope Variables have what is referred to as scope. The scope of a variable is directly related to the amount of other code that has access to the variable. Generally the smaller the scope of your variables the better off you are. That is why global variables are frowned upon. (defun my_prog ( / Var1 Var2) Var1 & Var2 are now local to only the my_prog function. If I had defined another function within my_prog the variables would have been accessible to it also. (defun my_prog ( / Var1 Var2) As you can see by the example Var1 and Var2 are accessible to sub_prog, because sub_prog was defined within my_prog. This is the basis for creating modules and will be discussed in later lessons. For now all you have to remember is if a variable is listed in the parameter list, its scope is confined to the function where it's listed. Purpose This type of mess should never happen, but sometimes due to time constraints or some other reason we just get into too big a hurry and things can go wrong. The best way to save yourself grief is to use a little defensive programming. Each variable you create should be used for one purpose and one purpose only. The most common variable to be used for two purposes is the index variable. If you are using the same index variable in two or more different places, you have not named your variables or your functions correctly. An index variable should have the function it's a part of, as part of its name. This will prevent you from indexing into a data structure at the wrong point because you have forgotten to initialize a variable before using it. Another thing to keep in mind when thinking about the purpose of a variable is to make sure you use all variables that you declare. Sometimes in the development of a program you change the way a function works, and declare new variables to match the way the modified function works. Be sure to clean up any old variables you may have set for the prior version. Global variables Problems Exceptions One of the big reasons to use global variables is to pass default values to your programs. If you are coding to make your program look and feel like built in AutoCAD commands, you will need to pass default values to your program. Global variables or an external file are good ways to save values from one run of your program to the next. There is another way to do this and avoid global data all together. AutoCAD has been supplying user system variables for you to use for several releases now, and this might be the best solution to the global variable problem. This is not however a fail proof system, as other programs may also be using the user system variables and write over your default values. Reduce risks Start writing your program with all variables local, and only make variables global as necessary. If you must increase the scope of a variable, try increasing its scope to the module level, before you make it global. In this way you can keep the number of global variables to a minimum. Remember to make global variables obvious. Naming them in a manner that you will know by looking at them is the best way to keep global’s straight. You may even consider listing global variables in the note comments at the header portion of your program. If global’s are listed someone doing maintenance to your program will be able to tell which variables are which. Access routines can be written to gain access to local variables from other function. If other function need access to local variables, try writing access routines before you just make the variables global. An access routine can control the access to the variable to any level and keep the variable from being changed. You can build a "read only" access level into the routines to protect your variables from outside modification. Throwing all your data into a big structure and accessing the data there is not protecting your data or making it easier to read or understand your program. When writing access routines the tendency is to write one big structure to hold everything, that way you only need one access routine to get to all the data. Data should be kept local to the modules using it, and multiple access routines should be written to get to the data in any module. Other variable considerations It's Magic Conversions If you divide an integer by a float you get a float. If you divide and integer by an integer you get an integer. This means that if you assign an integer to a variable you are treating like a float, the returned value will be an integer, which will be the wrong value. When assigning floating point numbers to variables always use trailing 0's. The trailing 0 assures a floating-point number and is easier to read when your trying to figure out what your program is up to. The FIX function will convert a float to an integer and the FLOAT function will convert an integer to a float. Strings This lets you change your program name or modify error messages in one place, and it will be reflected throughout your program. Summary |
|