TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: DanB on December 05, 2012, 11:46:59 AM

Title: Help with local, bound variable
Post by: DanB on December 05, 2012, 11:46:59 AM
I haven't touched any LISP routines in quite some time (unfortunately), so I am feeling a bit rusty to say the least. Can someone give me a basic rundown on the following example for localizing and/or bound variables ("mynumber" "yournumber") and where they should/could go in the routine.

Code: [Select]
(defun c:test ()
 (defun myaddit ()
  (+ mynumber yournumber)
 )
 (setq mynumber 2)
 (setq yournumber 3)
 (myaddit)
)
Title: Re: Help with local, bound variable
Post by: ronjonp on December 05, 2012, 11:54:44 AM
Code - Auto/Visual Lisp: [Select]
  1. (defun c:test (/ MYNUMBER YOURNUMBER)
  2.  (defun myaddit (mynumber yournumber)
  3.   (+ mynumber yournumber)
  4.  )
  5.  (setq mynumber 2)
  6.  (setq yournumber 3)
  7.  (myaddit mynumber yournumber)
  8. )
  9. ;;QUICK EXPLANATION
  10. (DEFUN XXX (ARGUMENTS> / <LOCALIZED VARIABLES) ... CODE )
Title: Re: Help with local, bound variable
Post by: DanB on December 05, 2012, 12:06:24 PM
Ok, how about in the below sample (moved the line code mynumber inside the defun)?

Code: [Select]
(defun c:test (/mynumber yournumber)
 (defun myaddit (mynumber yournumber)
  (setq mynumber 2)
  (+ mynumber yournumber)
 )
  (setq yournumber 3)
 (myaddit)
)
Title: Re: Help with local, bound variable
Post by: ronjonp on December 05, 2012, 12:40:59 PM
Dan .. what are you trying to do? Is this just an example? Typically if you're creating a function it is to do something that is not already available.

(+ 2 3)

 is the same as

(defun myaddit (mynumber yournumber)
  (+ mynumber yournumber)
 )

(myaddit 2 3)
Title: Re: Help with local, bound variable
Post by: dgorsman on December 05, 2012, 12:50:49 PM
Function arguments go before the "/", variable declarations after, and always good to put a space betwen them.  With no "/" its assumed all are arguments, so even if I don't have local variables declared I still add it just for clarity.

Variable useage is always from the inside out.  Those defined in the current function are used if declared, if not then the calling function, if not, then *that* calling function, and so on.  If a declared variable has the same name as one in a calling function then the local value is used rather than the one declared in the calling function.

Usually it works better to pass values as arguments to a function, then return the processed value.  Sometimes this isn't practical, such as complex operations in massively nested lists, so the variable in question would *not* be declared in the sub-function but still referenced, operating on the variable in the calling function.  But if this is coming up frequently its a good indication the program flow/logic needs revisiting.
Title: Re: Help with local, bound variable
Post by: DanB on December 05, 2012, 12:51:49 PM
Absolutely, just an example. Just to get myself back into things I was trying to come up with a simple example that I could apply the same principles to my code in progress. I think I have a need for defining a function within my new code and I wasn't quite sure how to handle the variables (i.e. it wasn't working).
Title: Re: Help with local, bound variable
Post by: CAB on December 05, 2012, 01:36:20 PM
More homework  8-)
-------------  LISP  Logic  -----------------
http://www.theswamp.org/index.php?topic=13046.msg158557#msg158557  by CAB
http://www.cadtutor.net/forum/showthread.php?52365-localizing-variables

-------------  Localizing Variables   ------------------
http://exchange.autodesk.com/autocad/enu/online-help/search#WS73099cc142f4875516d84be10ebc87a53f-7c3f.htm
http://exchange.autodesk.com/autocad/enu/online-help/search#WS1a9193826455f5ff18cb41610ec0a2e719-7358.htm
http://exchange.autodesk.com/autocad/enu/online-help/search#WS73099cc142f4875516d84be10ebc87a53f-7c3e.htm
http://exchange.autodesk.com/autocad/enu/online-help/search#WS1a9193826455f5ff18cb41610ec0a2e719-7356.htm
Title: Re: Help with local, bound variable
Post by: irneb on December 08, 2012, 02:50:46 AM
Something extra to this. You're defining the myaddit as a nested function. But the effect is not as a nested. E.g.
Code: [Select]
_$ (defun c:test (/ MYNUMBER YOURNUMBER)
  (defun myaddit (mynumber yournumber)
    (+ mynumber yournumber)
  )
  (setq mynumber 2)
  (setq yournumber 3)
  (myaddit mynumber yournumber)
)
C:TEST
_$ (myaddit mynumber yournumber)
; error: no function definition: MYADDIT
_$ (c:test)
5
_$ (myaddit mynumber yournumber)
_$ (myaddit 6 9)
15
Notice after C:Test is run, the myaddit function has become a global function. If you don't want this (i.e. you only want it inside the c:test containing function), then you'll need to declare it the same as you do for the variables mynumber & yournumber. Notice that they give a blank result when used outside of c:test? That's because they're released when c:test completes - that's what the declaration causes.

IMO, you should always declare a nested function as local - especially if you're going to directly work on variables of the main function. E.g.
Code - Auto/Visual Lisp: [Select]
  1. (defun c:test (/ MYADDIT MYNUMBER YOURNUMBER) ;Set all vartiables & functions as local to c:test
  2.   (defun myaddit ()
  3.     (+ mynumber yournumber) ;Use global variables in myaddit's scope
  4.   )
  5.   (setq mynumber 2)
  6.   (setq yournumber 3)
  7.   (myaddit)
  8. )
If you don't declare myaddit as local, then you end up having a myaddit function waiting around to try an use the mynumber / yournumber variables - which it expects to be global at the time of calling. Now that function may be called from somewhere else and depending on what is in those variable, or if they even exist, you might run into errors.

Not to mention (and probably much more dangerous) what if you have another definition of myaddit? Then some other code might expect that definition to be prevalent, but after you've run c:test the new definition is in effect - causing unexpected results and/or errors.
Title: Re: Help with local, bound variable
Post by: irneb on December 08, 2012, 03:08:43 AM
And BTW, I think what you're after trying to figure out is what's referred to as AutoLisp's "Dynamic Scoping". It's a bit difficult to figure out at first, especially since most other languages don't use dynamic - they use lexical scope instead. Even most other lisp dialoects don't use it (like Scheme) or relegate it to "special instances only" (like Common Lisp).

To explain the concept: In dynamic scoping there's one list of symbol names at all times. When a function declares a new symbol, that is added to the global list, when the function completes it's removed from that list. Lexical uses 2 lists at minimum: 1 for global variables and one for locals to the currently running function.

But the main difference is the effect this has on nested calls. In lexical only a truly nested function can "see" it's parent's local variables. But in dynamic even if one function calls another global function, the 2nd can "see" the 1st's variables. E.g. http://www.theswamp.org/index.php?topic=42230.5
Title: Re: Help with local, bound variable
Post by: DanB on December 13, 2012, 11:49:21 AM
Thanks irneb for your input as well. Real work keeps getting in the way of me spending more time on my desired lisp routine but I will get to it.