Author Topic: LISP Variables (Local, Global)  (Read 5831 times)

0 Members and 1 Guest are viewing this topic.

DanB

  • Bull Frog
  • Posts: 367
LISP Variables (Local, Global)
« on: February 14, 2005, 10:26:01 AM »
Could someone help explain and/or give an example(s) of how to maintain a default value from a previous user input. In my routine I would like the user to input an elevation change value (i.e. 1.5, 0.87) and when the routine is run in the same session to remember that input but also allow you to change at prompt. I'm not sure if leaving a variable global is appropriate/necessary for this application.

"snip-it of code"
Code: [Select]

;;
;; Portions of this Code supplied by Jeff_M and Others at the Swamp
;;

(defun C:Addsurf (/ acadObj1 aecApp1 aecProj aecSurfs aecSurf aecUtil pt# e-n selev newelev acadObj2 aecApp2 aecDoc

PrefDoc Hscale xsf ysf rta typ ctp ipt atr emsg elevdif elevc) ;; Removed BLK to "remember" last used Block Name

ALSO Removed chelev to "remember last User Elevation Change


Code: [Select]

  (if chelev
   (progn
    (setq chelev (rtos chelev))
    (setq elevdif (strcat "\nElevation Change: <" chelev "> "))
    (setq chelev (atof
      (if (= (setq elevc (getstring elevdif)) "") chelev elevc
       )
                  )
     )
    )
     (setq chelev (atof (getstring "\nElevation Change: ")))
   )


I'm just looking to see if I am going about this in the "right" way or not.
Thanks,
Dan

PS. Jeff_M - things are looking good for my Surface Lisp which this is part of, couldn't of done it without your help and all the rest here at the Swamp

SMadsen

  • Guest
LISP Variables (Local, Global)
« Reply #1 on: February 14, 2005, 10:53:36 AM »
I don't see anything wrong with creating global variables for the purpose of offering default values. Only if it's a value that needs careful preservation or should be saved from session to session, it would be preferrable to save it somewhere (e.g. in a dictionary or a system var - or perhaps, for cross-session use, in the registry).

Is there a specific reason for using GETSTRING to retrieve a number?

Mark

  • Custom Title
  • Seagull
  • Posts: 28762
LISP Variables (Local, Global)
« Reply #2 on: February 14, 2005, 10:55:55 AM »
As I see it there is several ways to do this, this is just one. It's not bullet proof my any means.
Code: [Select]

(defun c:myfunc ()
  (cond
((not ggg)                      ; if 'ggg' doesn't exist
(setq ggg (getreal "\nEnter value for 'ggg': "))
)
(ggg                            ; 'ggg' does exist prompt user to change
(if
  (=
(strcase
  (getstring (strcat "\nChange value ["(rtos ggg)"](Y/N)<No>: "))
  )
"Y"
)                          ; if the user answered with y/Y
                               ; then prompt for new value
  (setq ggg (getreal "\nEnter value for 'ggg': "))
  )
)
)
  (princ
(strcat "the value of 10 x " (rtos ggg)" = " (rtos (* ggg 10)))
)
  (princ)
  )
TheSwamp.org  (serving the CAD community since 2003)

JohnK

  • Administrator
  • Seagull
  • Posts: 10651
LISP Variables (Local, Global)
« Reply #3 on: February 14, 2005, 10:59:52 AM »
Here is a short example of how to use a global var.

Code: [Select]
;;; This procedure will use a global variable to prompt the
;;; user the number of times (s)he has called this procedure.
;;; This is only ment as an example.
(defun timesrun ()
  (if (eq _#times nil)
    (setq _#times 1)
    (setq _#times (1+ _#times))
    );_ end if
   (princ (strcat "\nYou have called this procedure " (rtos _#times 2 0) " times."))
   (princ)
 );_ end defun
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

JohnK

  • Administrator
  • Seagull
  • Posts: 10651
LISP Variables (Local, Global)
« Reply #4 on: February 14, 2005, 11:01:05 AM »
*shock* ...holy cow are you guys fast!

(I was beaten to the puch by not only one person but two!!??)
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

SMadsen

  • Guest
LISP Variables (Local, Global)
« Reply #5 on: February 14, 2005, 11:04:03 AM »
Don't forget, there is always the RRBDM (a.k.a. "Robert R. Bell Default Method")

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
LISP Variables (Local, Global)
« Reply #6 on: February 14, 2005, 11:47:33 AM »
Here is another approach to a routine that reuses settings.
If the variables are not changed frequently don't make the user press enter
to bypass the change. Just give them the option to change or continue without
interruption. In this example the user picks an insert point but has the option
of entering 'E' to reset the elevation or 'B' to change the block name.

I did not test the code so you will have to. :)

Code: [Select]
;;  Load a default if null variable
(setq chelev (cond (chelev) (10.0)))
(setq blknam (cond (blknam) ("ElevPt")))

;;  loop until user presses enter
(setq loop t)
(while loop
  (initget 1 "Elevation Block")
  (setq
    ptpick (getpoint
             (strcat "\nPick insert point or [Elevation / Block]: Elev="
                     chelev ": "
             )
           )
  )
  (cond
    ((= (type ptpick) 'list) ; point picked
     ;;  INSERT the block here
     ;;  Loop continuies to the next pick
     ;;  You could (setq loop nil) exit loop to allow only one insert
    )
   
    ((= ptpick "Elevation")
     ;;  get new elevation
     (setq newelev (getreal "\nEnter New Elevation: "))
     (if newelev
       (setq chelev newelev)
     )
    )

    ((= ptpick "Block")
     ;;  get new elevation
     (setq newblk (getstring t "\nEnter New Block name: "))
     (if (and newblk (tblsearch "Block" newblk))
       (setq blknam newblk)
       (alert "Block not found.")
     )
    )

    (t
     ;;  User pressed ENTER, so Bye Bye :)
     (setq loop nil) ; exit loop
  )
) ; end while
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

DanB

  • Bull Frog
  • Posts: 367
LISP Variables (Local, Global)
« Reply #7 on: February 14, 2005, 12:24:39 PM »
Thanks all, some good feedback here. I am very new to LISP writing, actually I am just trying to understand the processes and do more of Cut-n-Paste and some minor edits at this point. I don't consider myself a writer to say the least.

Quote

Is there a specific reason for using GETSTRING to retrieve a number?


Not really, more of lack of knowing any better. This was more of a case of Copy-N-Edit other code to do something "new." I will try to apply some of these concepts to better my code and look into (getreal)  :oops:

Thanks again
Dan

ronjonp

  • Needs a day job
  • Posts: 7529
LISP Variables (Local, Global)
« Reply #8 on: February 14, 2005, 12:26:02 PM »
Alright guys:

You got the ticker going and now it's broken :D .

Code: [Select]
 (initget 0 "Tree Shrub Bub Header Cv")      ;Gets T or S or B
  (if (not *default*)(setq *default* "S"))
  (setq P (getkword (strcat "\nEnter an option (T)ree, (S)hrub, (B)ub, (H)eader, or (C)v Lateral (" *default* "): ")))
  (if (not (eq P ""))(setq *default* P))



How do I get this section to accept the default? I've got it tt show the last user input....but thats it.

Thanks,

Ron

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

SMadsen

  • Guest
LISP Variables (Local, Global)
« Reply #9 on: February 14, 2005, 12:40:19 PM »
If it can help, here are some applications of the aforementioned default method. The first part is eqivalent to CAB's way of assigning global variables (only assigning each variable in case it evaluates to nil).

Code: [Select]
;; Setting up some global default values
;; unless already assigned
(foreach n '((str1_default "string_no_spaces")
             (str2_default "string with spaces")
             (int_default 89)
             (real_default 89.35)
             (key_default "Mykey")
            )
  (if (not (eval (car n)))
    (set (car n) (cadr n))
  )
)

(defun rrbdm_test (/ testType)
  ;; The default method used for determining which test to use
  ;; An empty response will assign the string "Keyword" to testType
  (initget 0 "keyString Getstring Integer Real Keyword")
  (setq testType
         (cond ((getkword
                  "\nTest GETxxx method [keyString/Getstring/Integer/Real/Keyword] <Keyword>: "
                )
               )
               ("Keyword")
         )
  )
  (cond ((= testType "Keyword")
         ;; GETKWORD default method
         ;; An empty response will assign key_default to variable default
         (initget 0 (strcat "Abc Def " key_default))
         (setq default (cond ((getkword (strcat "\nEnter keyword [Abc/Def/"
                                                key_default "] <"
                                                key_default ">: "))
                             )
                             (key_default)
                       )
         )
        )
        ((= testType "Real")
         ;; GETREAL default method
          (setq real_default (cond ((getreal (strcat "\Enter real <" (rtos real_default) ">: ")))
                                   (real_default)
                             )
          )
        )
        ((= testType "Integer")
         ;; GETINT default method
         (setq int_default (cond ((getint (strcat "\Enter integer <" (itoa int_default) ">: ")))
                                 (int_default)
                           )
         )
        )
        ((= testType "keyString")
         ;; Get a string default method
         ;; This one uses INITGET 128 which allows for arbitrary string input for GETKWORD, but
         ;; it doesn't accept spaces with the string
         (initget 128 str_default)
         (setq str1_default (cond ((getkword (strcat "\nEnter string w/o spaces <" str1_default ">: ")))
                                 (str1_default)
                           )
         )
        )
        ((= testType "Getstring")
         ;; Get a string defualt method
         ;; This one uses GETSTRING which allows spaces in the return value. On the other
         ;; hand it produces an empty string when getting an empty response so it can't be
         ;; tested for nil .. only for equal to "" (or STRLEN > 0, or some other predicate)
          (cond ((/= (setq str2_default (getstring T (strcat "\nEnter string <" str2_default ">: ")))
                     ""
                 )
                )
          )
         str2_default
        )
  )
)

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
LISP Variables (Local, Global)
« Reply #10 on: February 14, 2005, 12:41:06 PM »
Try this:
Code: [Select]
 (initget "Tree Shrub Bub Header Cv")      ;Gets T or S or B
  (if (not *default*)(setq *default* "S"))
  (setq P (getkword (strcat "\nEnter an option (T)ree, (S)hrub, (B)ub, (H)eader, or (C)v Lateral (" *default* "): ")))
  (setq p (cond (P)(*default*))
          *default* p)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

ronjonp

  • Needs a day job
  • Posts: 7529
LISP Variables (Local, Global)
« Reply #11 on: February 14, 2005, 12:42:16 PM »
You beat me CAB...


Code: [Select]
 (initget 0 "Tree Shrub Bub Header Cv")      ;Gets T or S or B
  (if (not *default*)(setq *default* "Shrub"))
  (setq P (cond ((getkword (strcat "\nEnter an option (T)ree, (S)hrub, (B)ub, (H)eader, or (C)v Lateral (" *default* "): ")))
  (*default*)))
  (if (not (eq P ""))(setq *default* P))

I got it to work like this but it's ugly :oops:

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
LISP Variables (Local, Global)
« Reply #12 on: February 15, 2005, 02:15:53 AM »
Food for thought.

(Admittedly probably overkill, but idea posted anyway).
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

sinc

  • Guest
LISP Variables (Local, Global)
« Reply #13 on: February 15, 2005, 04:27:44 PM »
Quote from: SMadsen
I don't see anything wrong with creating global variables for the purpose of offering default values. Only if it's a value that needs careful preservation or should be saved from session to session, it would be preferrable to save it somewhere (e.g. in a dictionary or a system var - or perhaps, for cross-session use, in the registry).

I'd just add that if you want to use global variables, its a good idea to use informal namespaces.  The name of your routine is a good choice for the informal namespace.

For example, say you have a routine called "MYTWEEK".  This routine asks for user input , and you want to store it in a global variable named *AREA*.  Obviously, being somewhat generic, you might have problems with other routines also trying to use a global variable named *AREA*.  A good way to prevent this is to name your global variable *MYTWEEK:AREA*.  A different program named FUNKYTOWN might also use a similar global variable, but would instead call it *FUNKYTOWN:AREA*.

This is called using an "informal namespace".  It is called "informal" because the use of the namespace is not parsed or enforced by the Lisp interpreter in any way.  The colon in the variable name is not any sort of special syntax, it is treated just like any other letter.  But chances of having a global variable named *MYTWEEK:AREA* in two different programs are slim indeed; much slimer than two programs both trying to use the global variable *AREA*.

At one point, I also posted this rough guideline about various ways to store user data in programs.

DanB

  • Bull Frog
  • Posts: 367
LISP Variables (Local, Global)
« Reply #14 on: February 15, 2005, 05:00:15 PM »
sinc, thanks for the feedback as well, I followed your posted link and copied the post for my future reference.  :D