Sittingbull Posted November 29, 2010 Posted November 29, 2010 (edited) Hi everyone, I just started with Lisp programming. At work we use a slide library for inserting blocks and run some function. One of them is making a material list by selecting the inserted block. It's working fine, but i'ld like someone to break it down for me. Many commands like "assoc", "car", "cdr" are new to me. By doing so i hope to get a better understanding of what i'ts doing. Two files(*.dwg) are used. The block to select from(inserted with the slide lib) and the actual matlis-block(apparently a block with the same name as the symbol+L?). So each symbol file has a second dwg file for the matlist block:?. Some how, these two are associated. I'ld like to understand how, so i can make new ones. (what does the "#" character do?) Here is the code: ;defines a new insert point ; (defun c:setpoint () (setq #inspoint (getpoint "\nNew insert point?:")) ) ; ;Inserts the matlist associated block, after selecting the symbol ; (defun c:insmatl (/ e1 et ed blnm #matlist #dist) (setq e1 (entsel "\nchoose symbol") e1 (car e1) ed (entget e1) et (cdr (assoc 0 ed)) ) (cond ((= et "INSERT") (setq blnm (cdr (assoc 2 ed))) (setq #dist 5.5 #matlist (strcat blnm "L") ) (if (null #inspoint) (setq #inspoint (getpoint "\nNew insert point?:")) ) (command "insert" #matlist #inspoint "" "" "") (setq #inspoint (polar #inspoint (dtr 90) #dist) ) ) ((/= et "INSERT") (setq #dist 5.5 ) (if (null #inspoint) (setq #inspoint (getpoint "\nNew insert point?:")) ) (command "insert" "matl" #inspoint "" "" "") (setq #inspoint (polar #inspoint (dtr 90) #dist) ) ) ) ) (princ) Edited November 30, 2010 by Tiger added codetags Quote
irneb Posted November 30, 2010 Posted November 30, 2010 Welcome & congrats on your 1st post! Firstly, if you're posting multiple lines of code please wrap it inside code tags - it's the # button when you're posting to this forum. For the 3 functions you refer to: assoc - Short for Associate. It works on a specialized list, called an association list. This type of list contains items which are themselves lists of at least 2 items each. The assoc searches through the list given a value for the 1st item inside the sublists. E.g. say you have a list (setq lst '((0 . "Zero") (1 . "One") (2 . "Two"))). So now (assoc 1 lst) will extract (1 . "One"). But (assoc 3 lst) will give nil, since there's no element with 3 as its own 1st item. car - Short for Copy Address Register (http://www.iwriteiam.nl/HaCAR_CDR.html). Basically it gives the 1st item in a list. So (car '(1 2 3 4 5)) gives 1. cdr - Short for Copy Decrement Register. This returns the remainder of a list, excluding the 1st element. So (cdr '(1 2 3 4 5)) gives (2 3 4 5). The previous 2 have some shortcuts which combine them to each other. E.g. (cadr '(1 2 3 4 5)) first does a cdr and then a car, so the result is 2. Some other things: strcat - String Concatenate ... not too difficult to understand. if - uhmmm yes ... :wink: = and /= - similar to equal and not equal. Not exactly the same as eq, which is not exactly the same as equal either. When comparing string values or lists, it's better to use eq as it compares the values to each other. = compares the variable references instead. And equal compares the values to a fuzz factor. set & setq - These save a value to a variable name, so you can reuse it later. Lisp uses dynamic variables, so the set needs to evaluate the variable's name. Thus to save a 1 into a variable named one you have to do (set (quote one) 1). The setq is a shorthand way of doing this, so (setq one 1) is an equal statement. Unfortunately AutoLisp / VisualLisp does not have the Common Lisp's setf function - which would have been a quick way of replacing an item in a list, e.g. say the list is (setq lst '(1 2 4 4)). Then doing (setf (caddr lst) 3) would produce a list (1 2 3 4). But as AutoLisp has split off from other lisps since the 80's we don't have these new nice functions to play with. http://stackoverflow.com/questions/869529/difference-between-set-setq-and-setf-in-common-lisp quote - Can be seen as analogous to stating "Reference". When you pass a variable to a function as an argument, lisp evaluates the variable to its value before running the function. So if you have (setq a 3) and then (+ a 2) lisp first evaluates a to 3 ... so it's as if you used (+ 3 2) instead. Usually this doesn't matter, but what if your function needs to modify the value inside a. E.g. say your function incements the value inside a: (defun inc (var) (if (= (type var) 'SYM) (set var (1+ (eval var))) (1+ var) ) ) ;; And then you have (setq a 3) ;; The following call will do noting to a's value (setq b (inc a)) ;b will get the value 4, but a will still be 3 ;; But (setq c (inc 'a)) ;Both c and a will now contain 4 (inc (quote b)) ;Only b will now contain 5 The shorthand way of using quote is to prefix with a single-quote ' defun - Short for Define Function. Rather self explanatory I think. cond - starts a Conditional statement. It would consist of a group of nested calls. It starts with the first in the "list of conditions". Checks if the 1st line in the current condition returns nil, if not it continues with that condition and then exists the cond. If nil, then jumps to the next condition and performs the same check there. null - toggles a variable between T/not-nil and nil. So if (setq a 3) then (null a) -> nil (can be seen as False). (null (null a)) -> T (True). The # doesn't actually mean anything. Lisp allows many characters in its variable or function names. So a lot of programmers use these "strange" characters simply to indicate some "special" aspect of the variable / function. It either becomes a convention or it's only relevant in their own minds. The rest of the functions are AutoCAD specific. You should look them up in the Developer Help. It does seem that it suffixes "L" onto the block's name ... you're correct. Quote
BIGAL Posted November 30, 2010 Posted November 30, 2010 code with explanantions (defun c:insmatl (/ e1 et ed blnm #matlist #dist) ; this is a defun or mini routine called from somewhere else and returns back to where it was called. (setq e1 (entsel "\nchoose symbol") ; select an object e1 (car e1) ed (entget e1) ; get the entity details of the object chosen et (cdr (assoc 0 ed)) ; find out what the object is assoc 0 ) (cond ((= et "INSERT") ; check to see if object is an autocad "insert" this means a block found (setq blnm (cdr (assoc 2 ed))) ; assoc 2 in this case is name of block (setq #dist 5.5 ; make #dist = 5.5 #matlist (strcat blnm "L") ;give the #matlist a L added to the blockname on the end ) If you look up assoc in lisp help you will find all the codes for different objects eg a Line 10 = start point 20 = end point then a car = x cadr =y caddr =z for the point. (car (assoc 10 ed)) = X value of start pt of a line. PS find replace # with nothing if it confuses you Quote
irneb Posted November 30, 2010 Posted November 30, 2010 Just a small fix: assoc gives everything including the code to be searched. So (assoc 10 ed) gives (10 ). Therefore to get the X you need to do (cadr (assoc 10 ed)), to get the Z (cadddr (assoc 10 ed)). Or to make it more "clear" (caddr (cdr (assoc 10 ed))). Or you could use the nth function: (nth 3 (assoc 10 ed)). Quote
Sittingbull Posted November 30, 2010 Author Posted November 30, 2010 Thanks a lot to all of you. It helps a lot. I'll read some more posts to get familiar with these and other codes. I'll try and modify this function. I think it would be better to have only one predefined block for the matlist. It's not logic to have duplicates for each symbol i insert. The symbols should have the attributes included and ready to extract. So the fuction could write those into the inserted matlist block, i think. thanks again for the clarifications Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.