Emmanuel Delay 发表于 2022-7-5 17:22:20

optional parameters - user inp

Is there a standard (good practice) way of handling optional parameters for functions?
 
 
---
 
 
The idea is: the user either
- selects an entity (entsel, ssget, ...) , fills in a value (getint, getstring, ...)
OR
- presses enter, then an other procedure takes over, or a default value gets set.
 
 
One concrete example,is a post I just answered, to insert (Lamp) blocks evenly spread in a room.
http://www.cadtutor.net/forum/showthread.php?88364-block-spacing-lisp&p=667270#post667270
 
 
Let's say this function is used 5 times in 1 dwg, and mostly with the same blockname, and the same number of rows and columns.It would be useful for the user if the function inserts the previous value if the user presses Enter
 
 
---
Here is an example
 

;; global variables with default values(setqglobal_blockname "LAMP" global_rows 2 global_cols 2);; notice, this function doesn't work; this is the problem(defun testfunction (blockname cols rows / ) (if (= nil blockname)   (setq blockname global_blockname) )(if (= nil cols)   (setq cols global_cols) )(if (= nil rows)   (setq rows global_rows) )   (princ blockname) (princ cols) (princ rows))(defun c:test ( / p1 p2) (testfunction    ;; user specifies a block   (setq global_blockname (getstring "\nBlock name: "))      ;; user gives 2 numbers x & y    (setq global_cols (getint "\nnumber of colums "))   (setq global_rows (getint "\nnumber of rows "))    ) (princ))
 
 
- (= nil ...) is not the answer.If I get this to work for different types of input, I think I can handle the rest.
 
 
- Overwriting a parameter, is that a wrong way doing it? Better declare extra variables instead?
 
 
- Setting global variables, to store default values; to store the previous values, ... in this a good idea?

Roy_043 发表于 2022-7-5 17:43:08

Some remarks:
1.
The (getstring) function never returns nil.
2.
In your c:test function you are overwriting global variables making your testfunction useless.
3.
There is nothing wrong with global variables. Most programmers will use them in this situation. But there can be name conflicts.
 
Maybe this is helpful:

(defun MyGetInt (msg def) ; Msg without "\n" and ": ". (cond   ((getint (strcat "\n" msg ": " (if def (strcat ": ") ""))))   (def) )); Note: function can return nil.(defun MyGetString (msg def / ret) ; Msg without "\n" and ": ". (cond   ((/= "" (setq ret (getstring T (strcat "\n" msg ": " (if def (strcat ": ") "")))))   ret   )   (def) ))(defun c:MyCommand ( / ) ... (if (not *myDefaultInt*) (setq *myDefaultInt* 2)) (setq *myDefaultInt* (MyGetInt "Default integer" *myDefaultInt*)) (if (not *myDefaultString*) (setq *myDefaultString* "Lamp")) (setq *myDefaultString* (MyGetString "Default string" *myDefaultString*)) ... ...)

Emmanuel Delay 发表于 2022-7-5 17:53:45

Thanks.
 
 
I'll see how best to use these elements, I'll try it out on that link I posted.
I suppose that use of (cond) is the basis of a solution.

broncos15 发表于 2022-7-5 18:04:51

I think that Lee Mac's tutorial is the best out there for how to prompt with a default option http://www.lee-mac.com/promptwithdefault.html. How I often do it when I am doing something like an entsel is (initget "Settings")   (setq sel   (entsel   "\\nSelect an object to do something : "   )   ) I then use a conditional that is based on what the user does.

BIGAL 发表于 2022-7-5 18:15:38

If you make your variable names very unique then you can keep them as global to end of a session. eg EM-val1 EM-val2
 
use a simple if this is a bit long winded but make it a defun and then its short 1 line call.
 

(if (= horiz nil)   (progn (setq horiz 100)   (prompt "\nEnter Horizontal scale::")   (setq newhoriz (getint))                           (if (= newhoriz nil)(PRINC "\N")(setq horiz newhoriz)         )   ); progn horiz

rlx 发表于 2022-7-5 18:31:07

Just one more little example I'm using right now. I have a paper copy of a layout that has to be redrawn in AutoCad. I measure a known distance with a known dimension to calculate a scale factor and from there on the routine returns the actual distance for every distance I measure until I cancel or enter 0 to recalibrate the scale factor. It stores this factor in a variable (rescale-factor) that is valid during the current drawing session.
 
 

;rescale - rescale-factor value will be remembered during drawing session(defun c:rescale ( / a b c) (if (not rescale-factor)   (cond   ;enter known distance in millimeters , trap cancel   ((= (vl-catch-all-error-p (setq a (vl-catch-all-apply 'getreal (list "\nReference distance as noted (mm) " )))) t)      (princ "\nInvalid input or user abort for noted reference distance"))   ((= (vl-catch-all-error-p (setq b (vl-catch-all-apply 'getreal (list "\nReference distance as measured (mm) " )))) t)      (princ "\nInvalid input or user abort for measured reference distance"))   (t (setq rescale-factor (vl-catch-all-apply '/ (list a b)))))) (if rescale-factor   (progn   (princ (strcat "\nCurrent rescale-factor = " (rtos rescale-factor)))   (princ "\nEnter new distances or 0 to reset")   (while (not (= (vl-catch-all-error-p (setq c (vl-catch-all-apply 'getreal (list "\nEnter new distance (mm) : " )))) t))(if (member c '(0 nil));reset rescale-factor(progn (setq rescale-factor nil)(c:rescale))(princ (strcat "\nRe-scaled distance = " (rtos (* rescale-factor c)))))))   (princ "\nUnable to find or set rescale-factor") ) (princ "\nRescale function ended") (princ))
 
 
gr.Rlx
页: [1]
查看完整版本: optional parameters - user inp