Lisp command unintentionally returns nil

Lisp command unintentionally returns nil

bbullock
Participant Participant
198 Views
8 Replies
Message 1 of 9

Lisp command unintentionally returns nil

bbullock
Participant
Participant

I am writing a program to calculate the weight of materials. I want to prompt for Lineal Footage under certain conditions, but I want to end the program with "Size Not Available" under all other conditions. For instance, if I answer STL to the "Material Type" prompt, 1/8 to the "U-Edge Clear Open" prompt, and 12 to the "Gauge" prompt, then I will be prompted for "Lineal Footage". This works great, but if I were to answer AL for "Material Type", and 1/2 for "U-edge Clear Open", I want the program to end with "Size Not Available", but it ends with "Size Not Availablenil". I have tried everything and can't seem to get rid of the nil at the end. Does anyone have a clue how to fix this? (Keep in mind that I haven't added anything for SS yet)

(defun c:UE (/ mt op ga lf wt)
  (initget "STL AL SS")
  (setq mt (getkword "\nMaterial Type: Steel<STL> Aluminum<AL> Stainless Steel<SS>:"))
  (initget "1/8 1/4 3/8 1/2")
  (setq op (getkword "\nU-Edge Clear Open: <1/8> <1/4> <3/8> <1/2>:"))
    (cond ((= mt "STL")
		(initget "12 14 18")
  		(setq ga (getkword "\nGauge: <12> <14> <18>:")))
	      ((= mt "AL")
	       (setq ga (= 0.063))
	       );end argument
	      );end condition
  	(cond 
	  ((= mt "STL")
	        (setq lf (getdist "\nLineal Feet:")))
	  ((and (= mt "AL") (= op "1/8"))
	   	(setq lf (getdist "\nLineal Feet:")))
	  ((and (= mt "AL") (= op "1/4"))
	   	(setq lf (getdist "\nLineal Feet:")))
	   (T
	  	(princ "Size Not Available")
	    	(princ)))
	(cond
	  ((and (= mt "STL") (= op "1/8") (= ga "12"))
		(setq wt (* lf 0.7990))
		(princ "\nWeight lbs:")
		(princ wt)
		(princ))
	  ((and (= mt "STL") (= op "1/8") (= ga "14"))
	   	(setq wt (* lf 0.5615))
	   	(princ "\nWeight lbs:")
	   	(princ wt)
	   	(princ))
	  ((and (= mt "STL") (= op "1/8") (= ga "18"))
	   	(setq wt (* lf 0.3542))
	   	(princ "\nWeight lbs:")
	   	(princ wt)
	   	(princ))
	  ;end 1/8" open Steel variations
	  ((and (= mt "STL") (= op "1/4") (= ga "12"))
	   	(setq wt (* lf 0.8246))
	   	(princ "\nWeight lbs:")
	   	(princ wt)
	   	(princ))
	  ((and (= mt "STL") (= op "1/4") (= ga "14"))
	   	(setq wt (* lf 0.5798))
	   	(princ "\nWeight lbs:")
	   	(princ wt)
	   	(princ))
	  ((and (= mt "STL") (= op "1/4") (= ga "18"))
	   	(setq wt (* lf 0.3665))
	   	(princ "\nWeight lbs:")
	   	(princ wt)
	   	(princ))
	  ;end 1/4" open Steel variations
	  ((and (= mt "STL") (= op "3/8") (= ga "12"))
	   	(setq wt (* lf 0.8502))
	   	(princ "\nWeight lbs:")
	   	(princ wt)
	   	(princ))
	  ((and (= mt "STL") (= op "3/8") (= ga "14"))
	   	(setq wt (* lf 0.5592))
	   	(princ "\nWeight lbs:")
	   	(princ wt)
	   	(princ))
	  ((and (= mt "STL") (= op "3/8") (= ga "18"))
	   	(setq wt (* lf 0.3783))
	   	(princ "\nWeight lbs:")
	   	(princ wt)
	   	(princ))
	  ;end 3/8" open Steel variations
	  ((and (= mt "STL") (= op "1/2") (= ga "12"))
	   	(setq wt (* lf 0.8773))
	   	(princ "\nWeight lbs:")
	   	(princ wt)
	   	(princ))
	  ((and (= mt "STL") (= op "1/2") (= ga "14"))
	   	(setq wt (* lf 0.6175))
	   	(princ "\nWeight lbs:")
	   	(princ wt)
	   	(princ))
	  ((and (= mt "STL") (= op "1/2") (= ga "18"))
	   	(setq wt (* lf 0.3900))
	   	(princ "\nWeight lbs:")
	   	(princ wt)
	   	(princ))
	  ;end 1/2" open Steel variations
	  ((and (= mt "AL") (= op "1/8"))
		(setq wt (* lf 0.1573))
		(princ "\nWeight lbs:")
		(princ wt)
		(princ))
	  ;end 1/8" open Aluminum
	  ((and (= mt "AL") (= op "1/4"))
	   	(setq wt (* lf 0.2187))
	   	(princ "\nWeight lbs:")
	   	(princ wt)
	   	(princ))
);end condition
  );end function

 

0 Likes
Accepted solutions (3)
199 Views
8 Replies
Replies (8)
Message 2 of 9

Kent1Cooper
Consultant
Consultant
Accepted solution

That's probably coming from the long (cond) function having no condition met, so the last operation in the function returns nil, which you're seeing because the end of any function always returns what the last operation in it returns.  Try putting the (princ) [which returns nothing, not nil] after the );end condition line, just above the );end function line at the end.  [And I think you could remove the (princ) lines from all those individual conditions.]

Kent Cooper, AIA
Message 3 of 9

Kent1Cooper
Consultant
Consultant
Accepted solution

Another approach would be to simply not permit the larger fractions when the metal is Aluminum:

(initget (if (= mt "AL") "1/8 1/4" "1/8 1/4 3/8 1/2"))
(setq op
  (getkword
    (strcat
      "\nU-Edge Clear Open: <1/8> <1/4>"; available for any metal
      (if (= mt "AL") "" " <3/8> <1/2>"); more choices if not AL
      ": "
    ); strcat
  ); getkword
); setq

Then you wouldn't need the size-not-available message coded in, because it would be covered by the "Invalid option keyword" prompt, and the routine would ask again until it is given a valid option, instead of giving up.

I'd also prefer to structure the (getkword) prompts in a way that would allow picking an option in the prompt itself if you want, instead of typing, but slashes in the fractions make that impossible, since those are reserved for separators between options.  [I tried to work around that a couple of ways, without success, but maybe there's a way.]  If you're willing to use something other than slashes, like 1'8, it could work that way, but people might get confused.  But the choice of metals could work that way, with for example S for Steel and ST for STainless, and the Aluminum option could be just A.

Kent Cooper, AIA
0 Likes
Message 4 of 9

bbullock
Participant
Participant
I removed all other instances of (princ) and moved it to the location that you suggested, and it worked beautifully. Thank you very much for the feedback!
0 Likes
Message 5 of 9

Moshe-A
Mentor
Mentor
Accepted solution

@bbullock hi,

 

A more efficient way to do it is to define a DATALIST that hold all data in one list than do inquiry on it see (get_whg) function.

it uses some advanced AutoLISP functions like (vl-some) and (lambda) but not something you can not learn and understand 😀 

here is my suggestion and if you need some explanation, i am here.

 

hope i did not miss any of the options 🙏

 

enjoy

Moshe

 

(defun c:UE (/ askint get_whg show_weight ; local functions
	        DATALIST mt op ga lf) ; local variables
  
 (defun askint (msg def / _pause val)
   
  (defun _pause ()
   (initget (+ 2 4))
   (if (not (setq val (getint (strcat "\n" msg " <" (itoa def) ">: "))))
    (setq val def)
    (setq def val)
   )
  ); _pause
   
  (while (null (member (setq ask (_pause)) '(12 14 18)))
   (vlr-beep-reaction)
   (prompt "\nAllowed value 12,14,18 only.")
  )

  ask
 ); askint

 (defun get_whg (mat opn gau)
  (vl-some
    (function
      (lambda (record / whg)
       (if (and
	     (eq mat (car record))
             (setq whg (vl-some
	                 (function
		           (lambda (data)
                             (if (and
		                   (eq opn (car  data))
		                   (=  gau (cadr data))
		                 )
		               (caddr data)
		             ); if
		           ); lambda
	                 ); function
	                 (cdr record)
	               ); vl-some
	     ); setq
           ); and
         whg  ; return 
       ); if
      ); lambda
    ); function
   DATALIST
  ); vl-some
 ); get_whg


 (defun show_weight (mat opn gau lfe / whg)
  (if (setq whg (get_whg mat opn gau))
   (princ (strcat "\nWeight lbs: " (rtos (* lfe whg) 2)))
   (princ "Size Not Available.")
  )
 ); show_weight 

  

 ; here start command c:ue

 ; const
 (setq DATALIST '(("STL" ("1/8" 12 0.7990) ("1/8" 14 0.5615) ("1/8" 12 0.3542)
                         ("1/4" 12 0.8246) ("1/4" 14 0.5798) ("1/4" 12 0.3665)
                         ("3/8" 12 0.8502) ("3/8" 14 0.5592) ("3/8" 12 0.3783)
                         ("1/2" 12 0.8773) ("1/2" 14 0.6175) ("1/2" 12 0.3900)
		  )
		  ("AL" ("1/8" 12 0.1573) ("1/4" 12 0.2187))
		 ); list
 ); setq
  
 (if (and
       (not (initget "STL AL SS"))
       (setq mt (getkword "\nMaterial Type: Steel<STL> Aluminum<AL> Stainless Steel<SS>: "))
       (not (initget "1/8 1/4 3/8 1/2"))
       (setq op (getkword "\nU-Edge Clear Open: <1/8> <1/4> <3/8> <1/2>: "))
     )
  (cond
   ((= mt "STL")
    (if (and
          (setq ga (askint "Gauge" 12))
          (setq lf (getdist "\nLineal Feet: "))
	)
     (show_weight mt op ga lf)
    ); if
   ); case
   ((= mt "AL")
    (setq ga 12) ; 0.063
    (if (setq lf (getdist "\nLineal Feet: "))
     (show_weight mt op ga lf)
    ); if
   ); case
   ( t
    (princ "Material Not Available.")
   ); cas
  ); cond
  
 ); if

 (princ)
); c:ue

 

 

 

Message 6 of 9

Sea-Haven
Mentor
Mentor

A couple of comments. @Kent1Cooper hinted at this one.

(setq wt (* lf 0.8773))
	   	(princ "\nWeight lbs:")
	   	(princ wt)

(princ (strcat "\nWeight " (rtos (* lf 0.7990) 2 2) " lbs:" ))

or 
(alert (strcat "\nWeight " (rtos (* lf 0.7990) 2 2) " lbs: " ))

I tend to use DCL's for choices rather than getkword, You could make the material choice then the correct options are displayed as either a child dcl or say list box next to the material. I have seen this done with up to 3 next list choices. So you would have Steel, then 1/8 1/4 3/8 1/2 then 12 14 18. Hopefully the author of 3 list boxes will supply you an answer, it may have been Lee-Mac. As I said I would use child dcl's.

SeaHaven_0-1758932904129.png

 

 

0 Likes
Message 7 of 9

bbullock
Participant
Participant
Those were some considerations I had when I began structuring this. In fact, I have since removed a couple of the sizes for aluminum as suggested and it works fantastic.
0 Likes
Message 8 of 9

bbullock
Participant
Participant

I like this method. I am going to take a closer look at this when I have the time so I can understand how this functions.

0 Likes
Message 9 of 9

Moshe-A
Mentor
Mentor

@bbullock ,

 

Ha, that's nice and i will help if you have question

meanwhile attached an update which is a bit simple to understand.

 

Moshe

 

0 Likes