Jump to content

Code's system variables


Grrr

Recommended Posts

Hi guys, I was trying to find the shortest way to store and reset a list of system variables. However I'm not a list manipulation guru so I need some help with the mapcar and lambda functions:

(defun C:test ( / vars )

; declare the list of variable names where each item is: (var-name-X new-var-val-X):
(setq vars '(("FILLETRAD" 10) ("CLIPROMPTLINES" 1) ("OSMODE" 0) ("CMDECHO" 0)))
; this should reconstruct the list where each item is: (var-name-X old-varval-X new-var-val-X)):
(setq vars (mapcar '(lambda (x) (list (car x) (getvar (car x)) (cadr x)) vars)))

; set the new values:
(mapcar '(lambda (x) (setvar (car x) (caddr x)) vars))

; perform var-check:
(foreach x vars
	(princ (strcat (car x) " with value: " (getvar (car x))))
)

(alert "\nThe main function starts!")

; restore the variable values:
(mapcar '(lambda (x) (setvar (car x) (cadr x)) vars))

; perform var-check:
(foreach x vars
	(princ (strcat (car x) " with value: " (getvar (car x))))
)

(princ)
); defun

The goal is to set only 1 quote named "vars" instead a bunch of quotes for each system variable. So we could all benefit from it :)

 

In other words (some tests copied from the visual lisp console):

_$ ; declare the list of variable names "vars" where each item is: (var-name-X new-var-val-X):
(setq vars '(("FILLETRAD" 10) ("CLIPROMPTLINES" 1) ("OSMODE" 0) ("CMDECHO" 0)))
(("FILLETRAD" 10) ("CLIPROMPTLINES" 1) ("OSMODE" 0) ("CMDECHO" 0))
_$ ; this should reconstruct the list to "nvars" where each item is: (var-name-X old-varval-X new-var-val-X)):
(setq nvars (list))
nil
_$ 
_$ (foreach itm vars 
(if (not (member (car itm) (mapcar 'car nvars)))
	(setq nvars (cons (list (car itm) (getvar (car itm)) (cadr itm)) nvars))
)
)
(("CMDECHO" 1 0) ("OSMODE" 15359 0) ("CLIPROMPTLINES" 4 1) ("FILLETRAD" 52.0 10))
_$ (setq nvars (reverse nvars))
(("FILLETRAD" 52.0 10) ("CLIPROMPTLINES" 4 1) ("OSMODE" 15359 0) ("CMDECHO" 1 0))
_$ ; set the new values:
(foreach itm nvars
(setvar (car itm) (caddr itm))
(princ (strcat "\n" (car itm) " : " (rtos (getvar (car itm)))))
)

FILLETRAD : 10.0000
CLIPROMPTLINES : 1.0000
OSMODE : 0.0000
CMDECHO : 0.0000"\nCMDECHO : 0.0000"
_$ (alert "\nThe main function starts!")
nil
_$ ; restore the variable values:
(foreach itm nvars
(setvar (car itm) (cadr itm))
(princ (strcat "\n" (car itm) " : " (rtos (getvar (car itm)))))
)

FILLETRAD : 52.0000
CLIPROMPTLINES : 4.0000
OSMODE : 15359.0000
CMDECHO : 1.0000"\nCMDECHO : 1.0000"
_$ 

But here I used 2 quotes "vars" and "nvars" - my question is is it possible to shorten it to only one "vars" and perhaps some overwriting (using mapcar/lambda instead of my newbie foreach approach).

Edited by Grrr
Link to comment
Share on other sites

Just me make the list a bit simpler (list "FILLETRAD" 10 "CLIPROMPTLINES" 1 "OSMODE" 0 "CMDECHO" 0)

 

Then just use a repeat function which is the length/2, nth x is the variable name nth x+1 is the value.

 

If you want you can make two lists and call a single defun passing the correct list name.

 

I get lost in lamba's sometimes so not sure how much shorter the defun would become or would be any real gain as its instant now.

 

(defun c:myvars ( / vars)
(setq vars (list "FILLETRAD" 10 "CLIPROMPTLINES" 1 "OSMODE" 0 "CMDECHO" 0))
(myvars vars)
)

(defun C:myvarsu ( / varsu )
(setq varsu (list "FILLETRAD" 10 "CLIPROMPTLINES" 1 "OSMODE" 47 "CMDECHO" 1))
(myvars varsu)
)

(defun myvars ( vars / x)
(setq x 0)
(repeat (/ (length vars) 2)
(setq sysvar (nth x vars))
(setq sysval (nth (+ x 1) vars))
(command sysvar sysval)
(setq x (+ x 2))
)
)

Edited by BIGAL
Link to comment
Share on other sites

I use dotted pairs

 

;++++++++++++ Set Modes ++++++++++++++++++++++++++++++++++
(defun nw_smd ()
(setq nw_var '(("CMDECHO"   . 0) ("MENUECHO"   . 0)
               ("MENUCTL"   . 0) ("MACROTRACE" . 0)
               ("OSMODE"    . 0) ("SORTENTS"   . 119)
               ("LUPREC"    . 2) ("MODEMACRO"  . ".")
               ("BLIPMODE"  . 0) ("EXPERT"     . 5)
               ("SNAPMODE"  . 1) ("PLINEWID"   . 0)
               ("ORTHOMODE" . 1) ("GRIDMODE"   . 0)
               ("ELEVATION" . 0) ("THICKNESS"  . 0)
               ("FILEDIA"   . 0) ("FILLMODE"   . 0)
               ("SPLFRAME"  . 0) ("UNITMODE"   . 0)
               ("TEXTEVAL"  . 0) ("ATTDIA"     . 0)
               ("AFLAGS"    . 0) ("ATTREQ"     . 1)
               ("ATTMODE"   . 1) ("UCSICON"    . 1)
               ("HIGHLIGHT" . 1) ("REGENMODE"  . 1)
               ("COORDS"    . 2) ("DRAGMODE"   . 2)
               ("DIMZIN"    .  ("PDMODE"     . 0)
               ("SNAPUNIT"  . (1 1))
               ("CECOLOR"   . "BYLAYER")
               ("CELTYPE"   . "BYLAYER")))
(foreach v nw_var
  (and (getvar (car v))
       (setq nw_rst (cons (cons (car v) (getvar (car v))) nw_rst))
       (setvar (car v) (cdr v))))
(princ))

;++++++++++++ Return Modes +++++++++++++++++++++++++++++++
(defun nw_rmd ()
 (foreach v nw_rst (setvar (car v) (cdr v)))
 (prin1))

 

I like the organized feel.

 

-David

Link to comment
Share on other sites

The goal is to set only 1 quote named "vars" instead a bunch of quotes for each system variable. So we could all benefit from it :)

 

But here I used 2 quotes "vars" and "nvars" - my question is is it possible to shorten it to only one "vars"

 

Personally, I would advise against overwriting your 'vars' variable when storing the existing system variable values, as you will also need to include an expression within a local error handler to reset the system variables if an error is encountered. Therefore, by using the same variable name, you would need to rely on testing for a different list structure in order to determine whether the 'vars' variable holds the stored system variable values or the new values (as the error may be encountered before or after the existing values are stored).

 

I would instead suggest using a separate variable to store the existing values, for example:

(defun c:test ( / *error* vals vars )

   (defun *error* ( msg )
       (foreach val vals (if val (apply 'setvar val)))
       (princ)
   )

   (setq vars
      '(
           (filletrad      10)
           (clipromptlines  1)
           (osmode          0)
           (cmdecho         0)
       )
   )

   (setq vals
       (mapcar
          '(lambda ( x / v )
               (if (setq v (getvar (car x)))
                   (progn(apply 'setvar x) (list (car x) v))
               )
           )
           vars
       )
   )

   ;; < do stuff >

   (foreach val vals (if val (apply 'setvar val)))
   (princ)
)

Though, sometimes you don't want to change the values of all system variables in the list at the same time, and so the following approach may be more appropriate:

(defun c:test ( / *error* vals vars )

   (defun *error* ( msg )
       (mapcar '(lambda ( a b ) (if b (setvar a b))) vars vals)
       (princ)
   )

   (setq vars '(filletrad clipromptlines osmode cmdecho)
         vals  (mapcar 'getvar vars)
   )

   ;; Change system variables as appropriate using separate setvar expressions

   (mapcar '(lambda ( a b ) (if b (setvar a b))) vars vals)
   (princ)
)

Note that the above examples also test whether the getvar expression returns a non-nil value when obtaining the existing system variable values, as not all system variables are available in all versions of AutoCAD.

 

...using mapcar/lambda instead of my newbie foreach approach.

 

I must say that there is nothing 'newbie' about using foreach; there are many solutions in which foreach is the most appropriate function for the task, for example: if you are iterating over items in a list and you are not using the values returned when processing the items, foreach is more appropriate than mapcar.

Link to comment
Share on other sites

Thanks for the help guys!

Lee, I revised your suggestions (thank you for posting them and your oppinion about this subject).

 

I did some modifications and tests from the codes you provided and ended up with this (commented version):

[b][color=BLACK]([/color][/b]defun c:test [b][color=FUCHSIA]([/color][/b] / *error* vars [b][color=FUCHSIA])[/color][/b]

[b][color=FUCHSIA]([/color][/b]defun *error* [b][color=NAVY]([/color][/b] msg [b][color=NAVY])[/color][/b]
	[b][color=NAVY]([/color][/b]princ [color=#2f4f4f]"\n>>> An error occured ! <<<"[/color][b][color=NAVY])[/color][/b]
	[b][color=NAVY]([/color][/b]princ [color=#2f4f4f]"\n>>>Restore the variables: "[/color][b][color=NAVY])[/color][/b] [b][color=NAVY]([/color][/b]princ [color=#2f4f4f]"\n"[/color][b][color=NAVY])[/color][/b]
	[b][color=NAVY]([/color][/b]foreach x vars [b][color=MAROON]([/color][/b]if [b][color=GREEN]([/color][/b]getvar [b][color=BLUE]([/color][/b]car x[b][color=BLUE])[/color][/b][b][color=GREEN])[/color][/b] [b][color=GREEN]([/color][/b]setvar [b][color=BLUE]([/color][/b]car x[b][color=BLUE])[/color][/b] [b][color=BLUE]([/color][/b]caddr x[b][color=BLUE])[/color][/b][b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b] [color=#8b4513]; assign original values[/color]
	[b][color=NAVY]([/color][/b]foreach x [b][color=MAROON]([/color][/b]mapcar 'car vars[b][color=MAROON])[/color][/b] [b][color=MAROON]([/color][/b]prin1 x[b][color=MAROON])[/color][/b] [b][color=MAROON]([/color][/b]princ [color=#2f4f4f]" : "[/color][b][color=MAROON])[/color][/b] [b][color=MAROON]([/color][/b]prin1 [b][color=GREEN]([/color][/b]getvar x[b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b] [b][color=MAROON]([/color][/b]princ [color=#2f4f4f]"\n"[/color][b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b] [color=#8b4513]; to perform print check[/color]
	[b][color=NAVY]([/color][/b]princ[b][color=NAVY])[/color][/b]
[b][color=FUCHSIA])[/color][/b]

[color=#8b4513]; here the user constructs an assoc list, where each item contains [b][color=FUCHSIA]([/color][/b]<variable name> <new variable value>[b][color=FUCHSIA])[/color][/b]:[/color]
[b][color=FUCHSIA]([/color][/b]setq vars [color=#8b4513]; [b][color=NAVY]([/color][/b]<var name> <new value>[b][color=NAVY])[/color][/b][/color]
	'[b][color=NAVY]([/color][/b]
		[b][color=MAROON]([/color][/b]filletrad      10[b][color=MAROON])[/color][/b]
		[b][color=MAROON]([/color][/b]clipromptlines  1[b][color=MAROON])[/color][/b]
		[b][color=MAROON]([/color][/b]osmode          0[b][color=MAROON])[/color][/b]
		[b][color=MAROON]([/color][/b]cmdecho         0[b][color=MAROON])[/color][/b]
	[b][color=NAVY])[/color][/b]
[b][color=FUCHSIA])[/color][/b]

[b][color=FUCHSIA]([/color][/b]princ [color=#2f4f4f]"\n>>>The original variables: "[/color][b][color=FUCHSIA])[/color][/b] [b][color=FUCHSIA]([/color][/b]princ [color=#2f4f4f]"\n"[/color][b][color=FUCHSIA])[/color][/b]
[b][color=FUCHSIA]([/color][/b]foreach x [b][color=NAVY]([/color][/b]mapcar 'car vars[b][color=NAVY])[/color][/b] [b][color=NAVY]([/color][/b]prin1 x[b][color=NAVY])[/color][/b] [b][color=NAVY]([/color][/b]princ [color=#2f4f4f]" : "[/color][b][color=NAVY])[/color][/b] [b][color=NAVY]([/color][/b]prin1 [b][color=MAROON]([/color][/b]getvar x[b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b] [b][color=NAVY]([/color][/b]princ [color=#2f4f4f]"\n"[/color][b][color=NAVY])[/color][/b][b][color=FUCHSIA])[/color][/b] [color=#8b4513]; to perform print check[/color]

[b][color=FUCHSIA]([/color][/b]if [b][color=NAVY]([/color][/b]not tempvars[b][color=NAVY])[/color][/b] [color=#8b4513]; check if there isn't such global variable[/color]
	[b][color=NAVY]([/color][/b]if
		[b][color=MAROON]([/color][/b]setq tempvars [color=#8b4513]; temporary assign the list to that variable[/color]
			[b][color=GREEN]([/color][/b]mapcar
				'[b][color=BLUE]([/color][/b]lambda [b][color=RED]([/color][/b] x / v [b][color=RED])[/color][/b]
					[b][color=RED]([/color][/b]if [b][color=PURPLE]([/color][/b]setq v [b][color=TEAL]([/color][/b]getvar [b][color=OLIVE]([/color][/b]car x[b][color=OLIVE])[/color][/b][b][color=TEAL])[/color][/b][b][color=PURPLE])[/color][/b]
						[b][color=PURPLE]([/color][/b]list [b][color=TEAL]([/color][/b]car x[b][color=TEAL])[/color][/b] [b][color=TEAL]([/color][/b]cadr x[b][color=TEAL])[/color][/b] v[b][color=PURPLE])[/color][/b][color=#8b4513]; [b][color=PURPLE]([/color][/b]<var name> <new value> <original value>[b][color=PURPLE])[/color][/b][/color]
					[b][color=RED])[/color][/b]
				[b][color=BLUE])[/color][/b]
				vars
			[b][color=GREEN])[/color][/b]
		[b][color=MAROON])[/color][/b]
		[b][color=MAROON]([/color][/b]progn
			[b][color=GREEN]([/color][/b]setq vars tempvars[b][color=GREEN])[/color][/b] [color=#8b4513]; re-quote the [color=#2f4f4f]"vars"[/color] list[/color]
			[b][color=GREEN]([/color][/b]setq tempvars nil[b][color=GREEN])[/color][/b] [color=#8b4513]; remove that global variable[/color]
		[b][color=MAROON])[/color][/b]
	[b][color=NAVY])[/color][/b]	
[b][color=FUCHSIA])[/color][/b]

[b][color=FUCHSIA]([/color][/b]princ [color=#2f4f4f]"\n>>> The code started ! <<<"[/color][b][color=FUCHSIA])[/color][/b]
[b][color=FUCHSIA]([/color][/b]princ [color=#2f4f4f]"\n>>> Changing the variables: "[/color][b][color=FUCHSIA])[/color][/b] [b][color=FUCHSIA]([/color][/b]princ [color=#2f4f4f]"\n"[/color][b][color=FUCHSIA])[/color][/b]
[b][color=FUCHSIA]([/color][/b]foreach x vars [b][color=NAVY]([/color][/b]if [b][color=MAROON]([/color][/b]getvar [b][color=GREEN]([/color][/b]car x[b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b] [b][color=MAROON]([/color][/b]setvar [b][color=GREEN]([/color][/b]car x[b][color=GREEN])[/color][/b] [b][color=GREEN]([/color][/b]cadr x[b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b][b][color=FUCHSIA])[/color][/b] [color=#8b4513]; assign new values[/color]
[b][color=FUCHSIA]([/color][/b]foreach x [b][color=NAVY]([/color][/b]mapcar 'car vars[b][color=NAVY])[/color][/b] [b][color=NAVY]([/color][/b]prin1 x[b][color=NAVY])[/color][/b] [b][color=NAVY]([/color][/b]princ [color=#2f4f4f]" : "[/color][b][color=NAVY])[/color][/b] [b][color=NAVY]([/color][/b]prin1 [b][color=MAROON]([/color][/b]getvar x[b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b] [b][color=NAVY]([/color][/b]princ [color=#2f4f4f]"\n"[/color][b][color=NAVY])[/color][/b][b][color=FUCHSIA])[/color][/b] [color=#8b4513]; to perform print check[/color]

[b][color=FUCHSIA]([/color][/b]getstring t [color=#2f4f4f]"\nInput something: \n"[/color][b][color=FUCHSIA])[/color][/b][color=#8b4513]; < do stuff >[/color]

[b][color=FUCHSIA]([/color][/b]princ [color=#2f4f4f]"\n>>>Restore the variables: "[/color][b][color=FUCHSIA])[/color][/b] [b][color=FUCHSIA]([/color][/b]princ [color=#2f4f4f]"\n"[/color][b][color=FUCHSIA])[/color][/b]
[b][color=FUCHSIA]([/color][/b]foreach x vars [b][color=NAVY]([/color][/b]if [b][color=MAROON]([/color][/b]getvar [b][color=GREEN]([/color][/b]car x[b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b] [b][color=MAROON]([/color][/b]setvar [b][color=GREEN]([/color][/b]car x[b][color=GREEN])[/color][/b] [b][color=GREEN]([/color][/b]caddr x[b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b][b][color=FUCHSIA])[/color][/b] [color=#8b4513]; assign original values[/color]
[b][color=FUCHSIA]([/color][/b]foreach x [b][color=NAVY]([/color][/b]mapcar 'car vars[b][color=NAVY])[/color][/b] [b][color=NAVY]([/color][/b]prin1 x[b][color=NAVY])[/color][/b] [b][color=NAVY]([/color][/b]princ [color=#2f4f4f]" : "[/color][b][color=NAVY])[/color][/b] [b][color=NAVY]([/color][/b]prin1 [b][color=MAROON]([/color][/b]getvar x[b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b] [b][color=NAVY]([/color][/b]princ [color=#2f4f4f]"\n"[/color][b][color=NAVY])[/color][/b][b][color=FUCHSIA])[/color][/b] [color=#8b4513]; to perform print check[/color]
[b][color=FUCHSIA]([/color][/b]princ [color=#2f4f4f]"\n>>> The code ended ! <<<"[/color][b][color=FUCHSIA])[/color][/b]

[b][color=FUCHSIA]([/color][/b]princ[b][color=FUCHSIA])[/color][/b]
[b][color=BLACK])[/color][/b][color=#8b4513];defun [/color]

 

Where the printed results in the console are:

 

-user successifuly ends the routine:

Command: TEST
>>>The original variables:
FILLETRAD : 245.0
CLIPROMPTLINES : 4
OSMODE : 15359
CMDECHO : 1
>>> The code started ! <<<
>>> Changing the variables:
FILLETRAD : 10.0
CLIPROMPTLINES : 1
OSMODE : 0
CMDECHO : 0
Input something:
some text
>>>Restore the variables:
FILLETRAD : 245.0
CLIPROMPTLINES : 4
OSMODE : 15359
CMDECHO : 1
>>> The code ended ! <<<
Command:

 

-user ends the routine with an error:

Command: TEST
>>>The original variables:
FILLETRAD : 245.0
CLIPROMPTLINES : 4
OSMODE : 15359
CMDECHO : 1
>>> The code started ! <<<
>>> Changing the variables:
FILLETRAD : 10.0
CLIPROMPTLINES : 1
OSMODE : 0
CMDECHO : 0
Input something:
*Cancel*
>>> An error occured ! <<<
>>>Restore the variables:
FILLETRAD : 245.0
CLIPROMPTLINES : 4
OSMODE : 15359
CMDECHO : 1
Command:

By removing the printchecks and the comments - the above code I posted, could be shortened up to:

(defun c:test ( / *error* vars )

(defun *error* ( msg )
	(foreach x vars (if (getvar (car x)) (setvar (car x) (caddr x)))) ; assign original values
	(princ)
)

; here the user constructs an assoc list, where each item contains (<variable name> <new variable value>):
(setq vars ; (<var name> <new value>)
	'(
		(filletrad      10)
		(clipromptlines  1)
		(osmode          0)
		(cmdecho         0)
	)
)
(if (not tempvars) ; check if there isn't such global variable
	(if (setq tempvars (mapcar '(lambda ( x / v ) (if (setq v (getvar (car x))) (list (car x) (cadr x) v))) vars)); (<var name> <new value> <original value>)
		(setq vars tempvars tempvars nil)
	)	
)

(foreach x vars (if (getvar (car x)) (setvar (car x) (cadr x)))) ; assign new values

(getstring t "\nInput something: \n"); < do stuff >

(foreach x vars (if (getvar (car x)) (setvar (car x) (caddr x)))) ; assign original values

(princ)
);defun 

Link to comment
Share on other sites

To each their own, but personally I really don't see the need for juggling the variables just so that you can reuse the 'vars' variable - this also relies on the 'vars' variable being immediately redefined with no errors encountered in the process, else the foreach expression within the local error handler will error.

Link to comment
Share on other sites

Thanks alot Lee!

You offered several cases for someone to use for their codes - and more importantly: in the shortest way possible.

Basically you are everywhere in this LISP world... (atleast I know when something clever comes up in someone's code - no wonder you were the guy to figure it out first or atleast have been a part from it).

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...