Jump to content

Local vs global variables - not very local and not so global either


vanowm

Recommended Posts

Hello.

 

My understanding of local variable within one function is it should not be accessible within other functions. However it seems not true, if other functions were called within original function.

(defun foo (/ test)
   (setq test "blah")
   (foo2)
   (princ)
)

(defun foo2 ()
   (print test)
)

The result:

_$ (foo)

 

"blah"

_$ (foo2)

 

nil

This opens quiet a few opportunities of sharing data within functions (sort of byRef), however it become more difficult to manage pollution of the script:

.
; === Top statistic:
; Function definition (with number of arguments): ((FOO . 0))
.
; === Top statistic:
[color=red]; Global variables: (TEST)[/color]
; Function definition (with number of arguments): ((FOO2 . 0))
; Check done.

Clearly the definition of "global" is stretch in this case, it's not truly global, now is it?

Link to comment
Share on other sites

You're neglecting to consider the scope of the calling function.

 

The nature of a local variable is not that it is only accessible from the calling function, and no others called within it's scope, but rather that local variables are returned to their original value for you following the end of a given Defun.

 

This nature is how one can successfully call *error* as local variable and not disrupt the OOTB native *error* handler, as one's custom defined *error* handler is merely processed within the scope of the calling function, and is then returned to its original definition (from startup).

 

Cheers

Link to comment
Share on other sites

Below is a response to an email I received from a user requesting clarification on the importance of declaring local functions & variables (notably, declaring the *error* function as local), it may help with your understanding:

 

In short, when you declare a symbol local to a function, you are effectively reserving the use of that symbol within the scope of the function. Any value that the symbol may hold outside of the scope of the function is stored, and the symbol is null within the function until defined. When the evaluation of the function has completed, the symbol retains the value it held outside of the scope of the function in which it is localised.

 

To demonstrate this effect, consider the following code:

(defun function1 ( / var1 )
   [color=green];; Print initial value of var1 within function1[/color]
   (princ "\nvar1 initial value within function1 = ")
   (princ var1)

   [color=green];; Define var1 local to function1[/color]
   (setq var1 "Value local to function1.")

   [color=green];; Evaluate function2[/color]
   (function2)

   [color=green];; Query the value of var1 within function1 after evaluating function2[/color]
   (princ "\nvar1 after evaluating function2 = ")
   (princ var1)
   (princ)
)

(defun function2 ( / var1 )
   [color=green];; Print initial value of var1 within function2[/color]
   (princ "\nvar1 initial value within function2 = ")
   (princ var1)

   [color=green];; Define var1 local to function2[/color]
   (setq var1 "Value local to function2.")
   (princ)
)

[color=green];; Define var1 globally:[/color]
(setq var1 "Global Value")

[color=green];; Evaluate function1[/color]
(function1)

;; Print the value of var1 following evaluation of function1
(princ "\nvar1 after evaluation of function1 = ")
(princ var1)

(princ)

Upon loading the above code, we have the following result:

var1 initial value within function1 = nil
var1 initial value within function2 = nil
var1 after evaluating function2 = Value local to function1.
var1 after evaluation of function1 = Global Value

As you can see, since variable var1 is declared local to both function1 & function2, its value is nil until defined within these functions (regardless of the value it held prior to evaluation of each function).

 

Also notice that var1 retains its string value "Value local to function1." after function2 has been evaluated.

 

Finally, after function1 has been evaluated, var1 reverts to its original globally defined value: "Global Value".

 

Now consider the result when var1 is not declared local to both function1 & function2:

(defun function1 ( / )
   [color=green];; Print initial value of var1 within function1[/color]
   (princ "\nvar1 initial value within function1 = ")
   (princ var1)

   [color=green];; Define var1 local to function1[/color]
   (setq var1 "Value local to function1.")

   [color=green];; Evaluate function2[/color]
   (function2)

   [color=green];; Query the value of var1 within function1 after evaluating function2[/color]
   (princ "\nvar1 after evaluating function2  = ")
   (princ var1)
   (princ)
)

(defun function2 ( / )
   [color=green];; Print initial value of var1 within function2[/color]
   (princ "\nvar1 initial value within function2 = ")
   (princ var1)

   [color=green];; Define var1 local to function2[/color]
   (setq var1 "Value local to function2.")
   (princ)
)

[color=green];; Define var1 globally:[/color]
(setq var1 "Global Value")

[color=green];; Evaluate function1[/color]
(function1)

[color=green];; Print the value of var1 following evaluation of function1[/color]
(princ "\nvar1 after evaluation of function1 = ")
(princ var1)

(princ)

When the above code is evaluated we obtain the following result:

var1 initial value within function1 = Global Value
var1 initial value within function2 = Value local to function1.
var1 after evaluating function2  = Value local to function2.
var1 after evaluation of function1 = Value local to function2.

As you can see, var1 is no longer 'reserved' within function1, and so retains its value defined outside of this function ("Global Value"); similarly, when function2 is evaluated, var1 already holds the value it held within function1 ("Value local to function1.").

 

Finally, observe that following evaluation of function1& function2, var1 is not restored to the value it held before these functions were evaluated: after being redefined within function2 to a value of "Value local to function2.", this value is retained when var1 is queried again within function1, and the value is still retained when var1 is queried globally after function1 has been evaluated.

 

For the same reason, in my Error Handling tutorial I declare the *error* symbol as local to the program to ensure that the original definition of this symbol is restored following evaluation of the program, and so that the redefined *error* function used by the custom program is not used globally.

 

This practice is described in more detail (and includes examples) under the heading: 'Restoring the Previous Error Handler' in my Error Handling tutorial.

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