Author Topic: Declaring variables in nested functions  (Read 25513 times)

0 Members and 1 Guest are viewing this topic.

Daniel J. Ellis

  • Swamp Rat
  • Posts: 811
Re: Declaring variables in nested functions
« Reply #15 on: February 05, 2009, 08:37:48 AM »
OK, thanks for your help everybody.  Trying to conclude:

  • If a subroutine produces a single variable, one can eliminate the call to the "produced" variable in the subroutine, simply calling the result of the operation in the subroutine, and declaring the variable in the outter function
  • If a subroutine produces more than one variable they can either be collected into a list, effectively mimicking a single variable, or one needs to SETQ nil those variables after their final use
  • Disregarding "lexical scope," which I'll discuss later, the only practical difference between SET and SETQ is that with SETQ, multiple pairings (SETQ a 1 b 2 c 3 etc) can be made in one statement, with SET they can't

Lexical Scope
From a quick internet search, it would appear that with a lexical scope, a variable can be assigned a value, but this value cannot be changed; if a dynamic scope is used the value of that variable can be changed as the program is run.
Based on Se7en's initial mention of lexical scoping, I take it that SET is lexical, while SETQ is dynamic?  On this basis I assume that (SET a (1+ a)) wouldn't work because a if fixed, whereas (SETQ b (1+ b)) would work because b is dynamic?

dJE
===
dJE

JohnK

  • Administrator
  • Seagull
  • Posts: 10604
Re: Declaring variables in nested functions
« Reply #16 on: February 05, 2009, 09:48:06 AM »
Well my train fell off its tracks.

Scope:

wikipedia?  No matter. Lexical and dynamic scoping is defined on how the interpreter searches for variables not necessarily what you can do to them per se. That is a loaded statement because the SEARCH can dictate the binding we may find, and if and how we can MODIFY that binding...Scope is a very broad subject that can cause your ears to ring.

Generally speaking:
Autolisp can look up a previously defined variable. SET and SETQ can modify the binding of those variables.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Declaring variables in nested functions
« Reply #17 on: February 05, 2009, 09:59:53 AM »
danellis,

I'am not sure to understand what you mean by "lexical scope" but I think you didn't undertsand the main difference between SET and SETQ.
Quote
I assume that (SET a (1+ a)) wouldn't work because a if fixed

(set a (1+ a)) won't work, but it's not because a is "fixed", it's because SET evaluates a and this evaluation returns a number, not a symbol.
IOW
(set a ...) is the same as (setq (eval a) ...)
(set (quote a) ...) is the same as (setq a ...)

Have look to this little squence on the commande line
Quote
Commande: (setq a 1)
1
Commande: (setq b (quote a)) ; this is the same as (setq b 'a)
A
Commande: !a
1
Commande: !b
A
Commande: (eval b)
1
Commande: (set b 2)
2
Commande: !a
2
Commande: !b
A
Commande: (eval b)
2
« Last Edit: February 05, 2009, 10:47:07 AM by gile »
Speaking English as a French Frog

JohnK

  • Administrator
  • Seagull
  • Posts: 10604
Re: Declaring variables in nested functions
« Reply #18 on: February 05, 2009, 10:08:51 AM »
<snip>
but I think you didn't undertsand the main difference between SET and SETQ.
<snip>

I dont think i understood the initial NEED.  ...I was aiming to eventually touch on the fact that SET can accept an evaluation as its first argument. I was wrong about his intentions and i said that i was mistaken and that i was sorry to lead him down the wrong path.  I will go back to my corner now.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

Daniel J. Ellis

  • Swamp Rat
  • Posts: 811
Re: Declaring variables in nested functions
« Reply #19 on: February 05, 2009, 12:51:29 PM »
My ears are completely ringing!!  Sorry about your train, I didn't mean to derail it lol

I often find wikipedia a good place to find fairly simple explaination of terms it that way. Obviously it (or more likely I), failed on this occasion.

I think I can put it in the "entirely irrelevant" category and forget all about it.  I'm aware that that was your original intention, I'd only caught on to it trying to find a difference between SET and SETQ.

Well my train fell off its tracks.

Scope:

wikipedia?  No matter. Lexical and dynamic scoping is defined on how the interpreter searches for variables not necessarily what you can do to them per se. That is a loaded statement because the SEARCH can dictate the binding we may find, and if and how we can MODIFY that binding...Scope is a very broad subject that can cause your ears to ring.

Generally speaking:
Autolisp can look up a previously defined variable. SET and SETQ can modify the binding of those variables.
===
dJE

Daniel J. Ellis

  • Swamp Rat
  • Posts: 811
Re: Declaring variables in nested functions
« Reply #20 on: February 05, 2009, 12:58:32 PM »
This thread had become me trying to establish the difference between SET and SETQ!!  "Scope" was a red herring of a word that at one point I thought might explain that difference.

I think I may understand now:
  • using SETQ one may assign a value to a variable, that value can be alphabetical, numerical, or the result of a function or of another variable
  • by way of contrast SET can only assign a variable to another variable
  • EVAL is a way of trying to make SETQ act like SET
  • QUOTE is a way of trying to make SET act like SETQ

dJE
danellis,

I'am not sure to understand what you mean by "lexical scope" but I think you didn't undertsand the main difference between SET and SETQ.
Quote
I assume that (SET a (1+ a)) wouldn't work because a if fixed

(set a (1+ a)) won't work, but it's not because a is "fixed", it's because SET evaluates a and this evaluation returns a number, not a symbol.
IOW
(set a ...) is the same as (setq (eval a) ...)
(set (quote a) ...) is the same as (setq a ...)

Have look to this little squence on the commande line
Quote
Commande: (setq a 1)
1
Commande: (setq b (quote a)) ; this is the same as (setq b 'a)
A
Commande: !a
1
Commande: !b
A
Commande: (eval b)
1
Commande: (set b 2)
2
Commande: !a
2
Commande: !b
A
Commande: (eval b)
2
===
dJE

JohnK

  • Administrator
  • Seagull
  • Posts: 10604
Re: Declaring variables in nested functions
« Reply #21 on: February 05, 2009, 01:29:41 PM »

no the only difference is that SETQ can NOT accept an evaluation as its first argument, SET can.
Code: [Select]
(setq a nil
      b nil
      c nil
      d nil)
; lets do some setup and clear a b c d vars just in case they are set.

(setq d 1)
; now create and one variable called d and fill it with the number 1

; pretending that we had a sitauation where we did not know what variable was used
; but we knew the range; we can run a small invesigation to discover it.

; to return the variable used...
(set
  ;; find the variable already defined (leave the others untouched)
  ;; and fill it with a number 7
  ;;
  ;; the second argument to SET can also be an evaluation
  ;; of a process but we are just going to set a number
  ;; for this example.
  (cond
    (a 'a)
    (b 'b)
    (c 'c)
    (d 'd) )
  7 )

; see the values of the variables to ensure that we didnt touch any other variable besides d
(mapcar 'eval '(a b c d))
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

Daniel J. Ellis

  • Swamp Rat
  • Posts: 811
Re: Declaring variables in nested functions
« Reply #22 on: February 05, 2009, 03:25:51 PM »
OK, let's see if I can understand that:

The setup is a nice and conventional SETQ.  :)

We've got a COND nested in a SET.
The COND looks at a, if a exists, turn it into a list
If a doesn't exist, it looks at b, and if that exists, turns it into a list
If b doesn't exist, the COND looks at c, and if that exists, turns it into a list
finally, if c doesn't exist, it looks at d, and if d exists, turns it into a list

The SET then turns assigns the value 7 to any variable that is a list.

That all seems to make sense, *except* that this seems to revolve around SET only working on lists, which you said earlier it didn't (you implied that SET can work on non-lists as well), unless the SET is filtering for the "nil"s, but then why would you need the COND statement?

It looks like SET can work on variables without knowing beforehand which variable it's working on.  Except that doesn't seem to save on any coding:
(COND
  ((a)(SETQ a 'a))
  ((b)(SETQ b 'b))
  ((c)(SETQ c 'c))
  ((d)(STEQ d 'd))
)

or would it start saving code if a more complicated example?

dJE


no the only difference is that SETQ can NOT accept an evaluation as its first argument, SET can.
Code: [Select]
(setq a nil
      b nil
      c nil
      d nil)
; lets do some setup and clear a b c d vars just in case they are set.

(setq d 1)
; now create and one variable called d and fill it with the number 1

; pretending that we had a sitauation where we did not know what variable was used
; but we knew the range; we can run a small invesigation to discover it.

; to return the variable used...
(set
  ;; find the variable already defined (leave the others untouched)
  ;; and fill it with a number 7
  ;;
  ;; the second argument to SET can also be an evaluation
  ;; of a process but we are just going to set a number
  ;; for this example.
  (cond
    (a 'a)
    (b 'b)
    (c 'c)
    (d 'd) )
  7 )

; see the values of the variables to ensure that we didnt touch any other variable besides d
(mapcar 'eval '(a b c d))

===
dJE

dustinthiesse

  • Guest
Re: Declaring variables in nested functions
« Reply #23 on: February 05, 2009, 03:50:09 PM »
The COND looks at a, if a exists, turn it into a list
If a doesn't exist, it looks at b, and if that exists, turns it into a list
If b doesn't exist, the COND looks at c, and if that exists, turns it into a list
finally, if c doesn't exist, it looks at d, and if d exists, turns it into a list

(a 'a) does not mean it is turning 'a' into a list.

While quote can be used to form lists, in this case the quote just returns the symbol without evaluating it.

Daniel J. Ellis

  • Swamp Rat
  • Posts: 811
Re: Declaring variables in nested functions
« Reply #24 on: February 05, 2009, 04:57:56 PM »
OK.

So a is still nil?
===
dJE

Daniel J. Ellis

  • Swamp Rat
  • Posts: 811
Re: Declaring variables in nested functions
« Reply #25 on: February 05, 2009, 04:59:54 PM »
Are you guys trying to tell me that I could for example

(SET a ( * 10))?

dJE
===
dJE

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Declaring variables in nested functions
« Reply #26 on: February 05, 2009, 05:15:14 PM »
To understand the difference between SET and SETQ, you have to understand the difference between EVAL and QUOTE (').

assigning a quoted expression to a variable
_$ (setq a (quote (+ 1 2)))
(+ 1 2)

the variable stores the unevaluated expression
_$ a
(+ 1 2)

forcing evaluation using eval
_$ (eval a)
3

SET always evaluates its first argument, so it's used with expressions which evaluation returns a symbol.
Here're three examples of set using

Code: [Select]
;;assigning a list of variables using mapcar
(setq pt (getpoint))
(mapcar '(lambda (sym val) (set sym val)) '(x y z) pt)

SET is needed because sym have to be evaluated to return x, then y, then z.
Repalacing SET by SETQ will avoid sym evaluation.
In the same way, to reset x,y and z to nil:

Code: [Select]
(foreach sym '(x y z) (set sym nil))
To create incremental variables SET can be used to evaluate a (read ...) expression which returns a symbol

Code: [Select]
(setq n 1)
(while (setq pt (getpoint))
  (set (read (strcat "pt" (itoa n))) pt)
  (setq n (1+ n))
)
« Last Edit: February 05, 2009, 05:20:16 PM by gile »
Speaking English as a French Frog

Daniel J. Ellis

  • Swamp Rat
  • Posts: 811
Re: Declaring variables in nested functions
« Reply #27 on: February 06, 2009, 08:03:13 AM »
OK, from another read of the thread, and a little trial-and-error on the command line, I think I understand, so here we go:

  • EVAL figures out what an expression actually means, so (EVAL (+ 1 2)) figuers out that 1 + 2 = 3
  • QUOTE just repeats an expression, so (QUOTE (+ 1 2)) would result in a display of "(+ 1 2)"  It leaves the expression completely alone, it just repeats it.
  • SETQ figures out what an expression actually means, and saves it to a variable, so (SETQ a (+ 1 2)) figures out that 1 + 2 = 3 and so saves 3 to a.  SETQ Can take anything, numbers, letters, or other variables as its input
  • SET is trying to be like SETQ, but can't quite manage it: it can only do stuff to other variables, so (SET a (+ 1 2)) produces an error, one first has to define variables for SET, such as (SETQ d 1 e 2) (SET a (+ d e)) would then look up d (1), look up e (2), then add them together (3) and save the result to a


dJE

(edit:  there's really no reason to quote the previous thread.)
===
dJE

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Declaring variables in nested functions
« Reply #28 on: February 06, 2009, 09:10:58 AM »
At the risk of muddying up the waters I'm going to step in here and offer my explanation.
You can scream & holler if I cause you any distress. :)

From the HELP file.
Quote
SET
The set function is similar to setq except that set evaluates both of its arguments whereas setq only evaluates its second argument.

Both set and setq expect a symbol as their first argument, but set accepts an expression that returns a symbol, whereas setq does not, as the following shows:

Code: [Select]
Command: (set (read "a") 5.0)
5.0

Command: (setq (read "a") 5.0)
; *** ERROR: syntax error

My examples of how you may use this feature of set.

Code: [Select]
;;  indirect set variables to nil
(mapcar '(lambda (x)(set (read x) nil)) (list "var1" "var2")) ; note that the variable name is in quotes!

;;  indirect set variables to value
(mapcar '(lambda (x y)(set (read x) y)) '("var1" "var2") '(2 3))

(+ var1 var2)
5

;;=========================================================
;;  get variables stored in list
(defun get_saved_vars ()
  ;;  extract variables from  global variable list
  (mapcar
    'set
    '(tid_filename  mtflag       pickangle     repeattxt
      repeatins     StripCodes   UpperCase     txtang
      useleader     usedimtxt    Keep:Dim      Keep:Txt
      Keep:Lay      Use:OvrRide  txt:lst:ptr   *DiaLoc*
      )
      textinsertdclvars  ; This variable is a list of values, see function below
  )
) ; defun get_saved_vars

;;=========================================================
;;  save variables in a global variable list
(defun put_saved_vars ()
  (setq textinsertdclvars
         (list
           tid_filename   mtflag       pickangle     repeattxt
           repeatins      StripCodes   UpperCase     txtang
           useleader      usedimtxt    Keep:Dim      Keep:Txt
           Keep:Lay       Use:OvrRide  txt:lst:ptr   *DiaLoc*)
  )
) ; defun put_saved_vars

;;=========================================================
If you are not comfortable with mapcar yet here is a foreach example.
Code: [Select]
;;  Change/Set values to zero
(foreach var '("mCount" "fCount" "hCount" "dCount" )
     (set (read x) 0)
)
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.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Declaring variables in nested functions
« Reply #29 on: February 06, 2009, 09:21:12 AM »
Here is one more example.
This will create variables with a prefix of "ListVar" and in this case it will create 7 different variables.
With this method you may create as many variables as needed.

Code: [Select]
;;  CAB 10.25.2007
(defun c:test (/ lst VarBase ndx)
  (setq lst     '(1 2 3 4 5 6 7)
        VarBase "ListVar"
        ndx     1
  )
  (foreach itm lst
    (set (read (strcat VarBase (rtos ndx 2 0))) itm)
    (setq ndx (1+ ndx))
  )
  (print ListVar3)
  (print ListVar6)
  (princ)
)
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.