AfraLISP - Learn AutoLISP for AutoCAD productivity

The (eval) Function

by Kenny Ramage

The (eval) function is another the seldom used but very powerful AutoLisp functions. It is defined in the AutoCad Customization Guide as follows :

Eval - Returns the result of evaluating an AutoLisp expression.
Syntax : (eval expr)

For example, have a look at the following code segment :

	(eval (ascii "A"))

Which simply means, Evaluate the expression (ascii "A"). This should return "65", the ASCII character code for "A".

Fine, I understand that, but where would I use it? Here's a simple example.

Say we had a whole lot of distances that we had to measure and then come up with an accumulative total. We could measure each one, write it down, and then, manually add them up. Here's a better way. We are now going to write an AutoLisp routine that allows us to measure each distance, and then return a total of all the distances. Here we will use the (eval) function to perform the final total calculation for us.

Here's the coding :

;Program to measure non-sequential distances
(Defun C:ADIST ( / dst dstlst adist)
;define the function and declare variables
  (setq dstlst '(+ )) 
  ;create list with plus
    ;while a return is not entered
 	(setq dst (getdist "\nPick point or Return to exit: "))
	;get the distance
       	(setq dstlst (append dstlst (list dst)))
	;append the distance to the list
	(setq adist (eval dstlst))
	;calculate the running total
	(setq dst (rtos dst 2 2))
	;convert to string
	(setq adist (rtos adist 2 2))
	;convert to string
	(princ (strcat "\nDistance = " dst "  Accum Dist = " adist))
	;display the distance and the running total
    );end while
	(prompt (strcat "\nTotal Distance = " adist))
	;display the total distance
   ;clean finish
;clean loading

We start of the function by defining a list that only contains the '+' function. The heart of the routine is nested in a 'while' loop. As long as the user keeps on adding distances, the routine runs, but as soon as he hits a return, 'while' evaluates to nil and the loop is ended. The first line within the loop simply gets the required distance. The second line appends the distances to the list. Thirdly, we evaluate the list adding all of the distances together. We then format the distance and the running total and display them to the user. Once the user has finished selecting the distances, we display the final total. Simple really!

Hint: Have you ever thought of building a macro recorder similar to that used in Excel. By storing the users AutoCAD commands in a list along with the AutoLisp command function, you could use the 'eval' function to 'playback' the list of commands. For example :

	(setq lst '(command "circle" pt2 rad))
	(eval lst)

Here's another example of using the (eval) function, but this time we'll use it to replace the (cond) function. The following coding is a small application that converts various values. It uses the (cond) function to determine which radio button was selected and then uses that information to run the relevant sub-routine.

First the DCL coding :

conversion   : dialog {
             label = "Conversion" ;
        : radio_button {
     	  key = "rb1" ;
     	  label = "&Inches to Millimetres" ;
     	  value = "1" ;
     	: radio_button {
     	  key = "rb2" ;
     	  label = "&Millimetres to Inches" ;
     	: radio_button {
     	  key = "rb3" ;
     	  label = "M&iles to Kilometres" ;
     	: radio_button {
     	  key = "rb4" ;
     	  label = "&Kilometres to Miles" ;
	: edit_box {
	  key = "eb1";
          label = "Value";
	  value = "1.0";
        ok_cancel ;

Save this as "Conversion.dcl".

And now the AutoLisp Coding :

(defun C:Conversion ()
  (setq retval "IM")
  (setq edval 1.0)
  (setq dcl_id (load_dialog "conversion.dcl"))
  (if (not (new_dialog "conversion" dcl_id)
  ;test for dialog
    ;exit if no dialog
  (mode_tile "eb1" 2)
  (action_tile "rb1" "(setq retval \"IM\")")
  (action_tile "rb2" "(setq retval \"MI\")")
  (action_tile "rb3" "(setq retval \"MK\")")
  (action_tile "rb4" "(setq retval \"KM\")")
    "(progn (setq edval (atof (get_tile \"eb1\")))"
    "(done_dialog) (setq userclick T))")
  );action tile
    "(done_dialog) (setq userclick nil)"	
  (unload_dialog dcl_id)
   (if userclick
     ((= retval "IM") (IM edval))
     ((= retval "MI") (MI edval))
     ((= retval "MK") (MK edval))
     ((= retval "KM") (KM edval))
  );if userclick
  (alert (strcat "Value = " (rtos ans)))
(defun IM (val)
 (setq ans (* val 25.4))
(defun MI (val)
 (setq ans (/ val 25.4))
(defun MK (val)
 (setq ans (* val 1.609344))
(defun KM (val)
 (setq ans (/ val 1.609344))

Save this a "Conversion.lsp" then load and run it.

As you will see, it's just a simple little conversion routine.

Now replace these lines :

     ((= retval "IM") (IM edval))
     ((= retval "MI") (MI edval))
     ((= retval "MK") (MK edval))
     ((= retval "KM") (KM edval))

with this line :

((eval (read retval)) edval)

This one line replaces the whole of the (cond) section.

Cheers for now and happy evaluating…