Notifications
Clear all

[Closed] Local variables vs straight-up variables

Hi there!

  I already understand the differences between local and global variables but I'm curious as to whether it would be a good habit to form to declare variables as local in (almost) every case.
  
  Reason I'm asking is that I've been working on a pretty hefty script in terms of how much code I'm putting in and came across threads that discuss memory issues.
  
  So, aside from variables like "i" for basic for-loops and the like that will always be used in this manner and over-written frequently, what about other ones like :
p = point()
  Would it be a good practice to get into the habit (whenever the variable isn't going to be used outside of that particular sub-routine/algorithm) of making them like:

    local p = point()
    local c = circle()
      
     --or--
      
      local p = point(), c = circle()
  
  --or--
  
  local 
     p=point(),
     c=circle()
   
  Your thoughts? Would this help keep memory issues at bay by making the sub-routine specific variables as always local so that they're purged from memory when they are no-longer needed?
7 Replies
1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

it’s absolutely ok for me use short, simple, common used names for local variables:
p as point, v as vertex, f as face (or file), vv as array of vertices, sp as spline, etc.

but if these variables are not used everywhere across a local code. short names should be used as some sort of a temp variable (like an index in loop)

   local p = point()
   local c = circle()
     
    --or--
     
     local p = point(), c = circle()
 
 --or--
 
 local 
    p=point(),
    c=circle()
 
         

i usually use a multi-line declaration. especially if i do declaration with assignment. but if it’s a ‘static’ assignment it’s OK for me to write it in one line:


  local a, b -- good
  local x = 0, y = 0 --good
  local p = point(), b = box() -- not good
  local v = polyop.getvertsusingface $ $.selectedfaces, mats = for m in meditmaterials collect m.name -- very bad  
  
 PEN

Local infers that there is something that it is local to.

(
     local p=point()
)

Keeping code on separate lines makes it more readable.

 lo1

You seem to have a misconception regarding locality.

When declared inside a subroutine, and not explicitly marked global, all variables will be implicitly declared local, whether you mark them local or not.

The codes

(
    p = point()
)

and

(
    local p = point()
)

(notice the declaration is inside a block)
Are identical in terms of execution and performance.

Nevertheless, you should ALWAYS ALWAYS ALWAYS explicitly mark the scope of every variable (with the exception of loop indexers), and try to give it a meaningful name.

This really improves readability of your code. Simply looking at a variable, you immediately know if you’re looking at a local variable or not. Even if no one else is going to ever look at the code except yourself, future you will thank you for this.

Thank you to everyone for the responses!

So, understanding this, is that to suggest that declaring a variable as local that it will only be accessible from within the subroutine that it’s in and doesn’t really impact memory-use?

If the variable or function was already declared as global either in your script or in another script, wouldn’t you overwrite it if you don’t declare it as local?

Also, declaring local variables inside loops seems to slow them down. But you should declare them as local, not only for readability, but to prevent them overwriting any previously declared global with the same name.

(
  	global g = 10
  	global myTestFunction
  	fn myTestFunction = (print "----- GLOBAL FUNCTION";ok)
  )
  format "----- g=%
" g
  myTestFunction()
  
  (
  	local g = 0
  	local myTestFunction
  	fn myTestFunction = (print "----- LOCAL FUNCTION";ok)
  )
  format "----- g=%
" g
  myTestFunction()
  
  (
  	g = 5
  	fn myTestFunction = (print "----- I HAVE REPLACED A GLOBAL FUNCTION";ok)
  )
  format "----- g=%
" g
  
  (
  	gc()
  	st = timestamp()
  	for j = 1 to 1000000 do
  	(
  		a = j
  	)
  	format "%ms
" (timestamp()-st)
  	
  	gc()
  	st = timestamp()
  	for j = 1 to 1000000 do
  	(
  		local a = j
  	)
  	format "%ms
" (timestamp()-st)
  )
  myTestFunction()
2 Replies
 lo1
(@lo1)
Joined: 11 months ago

Posts: 0

Yes, of course, that’s not a declaration, that’s just reading/writing an existing variable.

To be fair, I see a difference of 100ms per 1 million iterations, that’s 0.1 MICROseconds per iteration, which is insignificant in maxscript terms.

Moreover, there’s no real reason to declare ‘a’ inside the loop. it can be explicitly declared local outside the loop, which avoids the performance penalty.

gc()
  	st = timestamp()
	local a
  	for j = 1 to 1000000 do
  	(
  		a = j
  	)
  	format "%ms
" (timestamp()-st)
(@polytools3d)
Joined: 11 months ago

Posts: 0

I would say, if you don’t explicitly mark a variable, either local or global, it will just inherit its scope. Except if you are in a local scope and you don’t “mark” a variable as local, and it was previously declared as global by your Script or by other Script.

 Then you might think you have a local variable, but you would be overwriting a global without knowing it.
 
 In my opinion, this is one of the most solids reasons to explicitly declare your variables as local (if you need to). Not only because you could overwrite a global, but because other script could overwrite yours too.

Regarding the local variable inside a loop. While in this example you can make “a” local variable outside the loop, you know that’s not the point of the example. And many times you will need to declare locals inside loops.

    About the speed, there are different ways of "reading" the results:
    
    241ms        Without declaring as local
    320ms        Declaring as local
    
    I see a 30% difference, not 0.1 microsecond. You could try with more variables and measure the results.