Author Topic: Poco loco..  (Read 4064 times)

0 Members and 1 Guest are viewing this topic.

Water Bear

  • Guest
Poco loco..
« on: February 27, 2004, 03:40:53 PM »
Say if I declare a defined function as local, does that automatically make all variables within it local as well, though I haven't defined them as such? :roll:

Columbia

  • Guest
Poco loco..
« Reply #1 on: February 27, 2004, 05:09:33 PM »
The short answer is...nope.  All variables that you want localized have to be in the variable list in a parent level defun.  If not, then they are Global.

Thus if they are never listed in the variable list of a defun, then they are never local...in that drawing session...

SMadsen

  • Guest
Poco loco..
« Reply #2 on: February 27, 2004, 05:21:01 PM »
Some illustrations.

Code: [Select]

;; Sample 1  :-(
;; No local symbols are declared. Function LOCAL will be loaded and
;; become global when called by MAIN. Var a becomes global.
(defun main ()
  (defun local ()
    (setq a 1.0)
  )
  (local)
)

;; Sample 2  :-(
;; Var a is declared local to MAIN. However, function LOCAL will be
;; loaded and become global when called by MAIN. Var a will stay
;; local, but only to MAIN. If function LOCAL is called from outside,
;; variable a will become global.
(defun main (/ a)
  (defun local ()
    (setq a 1.0)
  )
  (local)
)

;; Sample 3  :-(
;; Function LOCAL is declared local to MAIN and will not become global.
;; However, variable a will be global when function LOCAL has been called.
(defun main (/ local)
  (defun local ()
    (setq a 1.0)
  )
  (local)
)

;; Sample 4  :-)
;; Function LOCAL is declared local to MAIN and will not become global.
;; Variable a is declared local to LOCAL and will not become global.
(defun main (/ local b)
  (defun local (/ a)
    (setq a 1.0)
  )
  (setq b (local))
)

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Poco loco..
« Reply #3 on: February 27, 2004, 06:44:23 PM »
Well you learn something every day.
i was under the wrong impression that a defun within a defun made it local.
Did not know you had to declare it.
Also was under the wrong impression that a declared local variable was local
to functions defined within the defun.

Thanks for the clarification.

CAB
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.

SMadsen

  • Guest
Poco loco..
« Reply #4 on: February 28, 2004, 06:40:59 AM »
A function name is but a symbol. There's no real difference between SETQ'ing a symbol and DEFUN'ing it.

First time the parent function calls the nested DEFUN, it will evaluate it just like any other expression and, much like using SETQ, it will cause the function symbol to be assigned.
Not declaring a nested DEFUN as local can cause bugs that are hard to find. "So what! I would never call a DEFUN nested within another DEFUN from the outside". Besides creating needless global symbols, it could just happen that a routine with the same name was run. Especially when not being aware of the fact that a nested DEFUN becomes global if not declared local within the parent, it might be assumed that there will be no name conflicts.

Say you like the name getValue and (perhaps subconsciously) use the name for both a main level function and a nested function:

Code: [Select]
(defun getThisValue (/ a)
  (defun getValue ()
    (princ "Level 2")
    (setq a 1.0)
  )
  (getValue)
)

(defun getValue (/ a)
  (princ "Level 1")
  (setq a 2.0)
)

(defun doIt (/ x y z)
  (setq x (getValue))
  (terpri)
  (setq y (getThisValue))
  (terpri)
  (setq z (getValue))
  (princ)
)


Try load the 3 functions above and run DOIT. Here's a test output:

_$ (doIt)
Level 1
Level 2
Level 2

Which function does the last call in DOIT run? Try run it again without reloading it:

_$ (doIt)
Level 2
Level 2
Level 2

Why will the main level function GETVALUE never be run? Try inspect the value of variable a. If it was declared local to both functions called by DOIT, why is it not nil?

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Poco loco..
« Reply #5 on: February 28, 2004, 08:47:42 AM »
Very good example..

You were probably directing you question to WaterBear
so here is my answer in ascii code, No peaking WaterBear :)

Code: [Select]
(vl-list->string'(87 104 101 110 32 108 111 97 100 101 100 32 116 104 101 32 102 105 114 115 116 32 116 105 109 101))
(vl-list->string'(71 101 116 86 97 108 117 101 32 76 101 118 101 108 50 32 105 115 32 110 111 116 32 108 111 97 100 101 100 44))
(vl-list->string'(71 101 116 86 97 108 117 101 32 76 101 118 101 108 49 32 105 115 32 100 101 102 ))
(vl-list->string'(105 110 101 100 32 97 115 32 103 108 111 98 97 108 46))
(vl-list->string'(98 117 116 32 119 104 101 110 32 103 101 116 84 104 105 115 86 97 108 117 101 32 105 115 32 114 117 110))
(vl-list->string'(71 101 116 86 97 108 117 101 32 76 101 118 101 108 50 32 105 115 32 108 111 97 100 101 100 32 97 110 100))
(vl-list->string'(109 97 100 101 32 103 108 111 98 97 108 32 97 108 115 111 32 116 104 117 115 32 111 118 101 114))
(vl-list->string'(119 114 105 116 105 110 103 32 116 104 101 32 71 101 116 86 97 108 117 101 32 76 101 118 101 108 49 46))


Thanks Stig

CAB
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.

Water Bear

  • Guest
Poco loco..
« Reply #6 on: February 28, 2004, 10:40:49 AM »
:shock: OK, now that my eyeballs are all dried up and smoke is billowing from my ears...lets see if I can't get this ChupaCabras by the tail!
*on load, you've set getvalue to level 2
*then reset getvalue to level 1
*x returns level 1
*y re-runs getvalue and sets it to level 2
*z since getvalue has been left global it returns level 2

*second instance of "doit"
*x, y, and z since getThisValue=getvalue that has been left global all variables    return level 2 using the getvalue routine that is in memory

..but suppose I did this:
Code: [Select]
(defun getThisValue (/ a)
  (defun getValue ()
    (princ "Level 2")
    (setq a 1.0)
    )
  (getValue)
;;;)

  (defun getValue (/ a)
    (princ "Level 1")
    (setq a 2.0)
    )

  (defun doIt (/ x y z)
    (setq x (getValue))
    (terpri)
    (setq y (getThisValue))
    (terpri)
    (setq z (getValue))
    (princ)
    )
  ) ;<===== moved
Now what have I got? Why do I get:
_$ (doit)
Level 1
Level 2
Level 1
_$ (doit)
Level 1
Level 2
Level 1

Isn't getvalue= level 2...and should stay there?

SMadsen

  • Guest
Poco loco..
« Reply #7 on: February 28, 2004, 09:05:46 PM »
lol CAB :D
I was just throwing out some hypothetical questions without intention of them being answered. But you're absolutely right with your "encrypted" answers  :)

Water Bear,
If you are nesting all functions within GETTHISVALUE, you would not be able to call DOIT without it being evaluated first. Therefore I will guess that you tested the code you posted while DOIT was still loaded as a separate function from my previous posting. So, and please don't take this the wrong way, your question have no relevance. To see what I mean, you need is to set DOIT to nil, reload the code you posted (and only that) and then call it. DOIT will not be recognized as a function because it is nested.

However, if you do this, you will see that GETVALUE are duplicate functions on the same nested level. Therefore the last evaluated of the duplicate functions will take precedence. Following from my earlier conclusion, the last evaluated GETVALUE will then become global and call-able from the outside. Calling GETVALUE will of course evaluate the last evaluated GETVALUE which will be the "level 1" one (returning 2..0).

Otherwise, your initial answers in your post are correct.