Scope: Difference between revisions

From Legacy Roblox Wiki
Jump to navigationJump to search
>Camoy
(Local Variables, Setfenv, Scope)
m (Text replacement - "</SyntaxHighlight>" to "</syntaxhighlight>")
 
(24 intermediate revisions by 8 users not shown)
Line 1: Line 1:
{{CatUp|Tutorials}}
==What is Scope?==
__TOC__
Scope is a block of code in which variables are declared. {{`|for}} loops, {{`|while}} loops, {{`|repeat until}} loops, {{`|functions}}, {{`|if then}}, and {{`|do end}} chunks all create a new variable scope. For most of the following examples, the {{`|do end}} chunk will be used as a simple way of creating a variable.


== Introduction ==
Variables can be declared in two ways: local (with the {{`|local}} keyword), and global. Global variables are ''always'' in scope: no matter where you declare them, they are always accessible.


This tutorial will introduce you to <b>scopes</b> of [[Variables]]. It is recommended that you are familiar with the [[Variables]] and [[Functions]] tutorial.
{{Example|<syntaxhighlight lang="lua">
function myFunction()
myVariable = 64 --globally scoped
end
 
myFunction()
 
print("myVariable is " .. myVariable)


== Discussion ==
Output:
myVariable is 64
</syntaxhighlight>}}


A <b>scope</b> is what can access a variableLet's try, for example, printing the value of a variable that was declared in a function. The following will give us an error:
When ''myFunction'' was called, myVariable was set to 64.  Since this variable is globally scoped, it could be accessed outside the functionThis is why the output was "myVariable is 64". Take a look at this example using the {{`|local}} keyword to change the scope of a variable.


<pre>
<syntaxhighlight lang="lua">
function myFunction()  
function myFunction()
myVariable = 64
local myVariable = 64
end
end


print("myVariable is " .. myVariable)
myFunction()
</pre>


The variable 'myVariable' was declared inside myFunction, and myVariable was created when myFunction was run. Once myFunction ends, myVariable no longer exists.  That is why you can't "print" myVariable outside of this function.
print("myVariable is " .. myVariable) --> myVariable is nil
</syntaxhighlight>


How do you print myVariable?  
"myVariable is nil" was outputted because myVariable was confined to myFunction's environment or its scope. Therefore, it was not able to access the value outside of that function.


You can declare outside of the function to have a "global scope."
Global variables can be set easily by removing the word local, but for even better control over a variables scope, you can use setfenv.


<pre>
{{Example|<syntaxhighlight lang="lua">
myVariable = 64 -- this value is declared outside of the function
function myFunction()
function myFunction()  
function myFunction2()
print(a)
end
myFunction2()
print(a)
end
end
print("myVariable is " .. myVariable)
setfenv(myFunction, {a = 64,print=print})
</pre>
myFunction()
print(a)
 
--[[
Output:
64
64
nil
]]
</syntaxhighlight>}}
 
This will output two values of 64, and will output one nil.  The variable's environment was set to the function 'myFunction', and therefore the variable was also accessible by descendant environments (myFunction2).  The setfenv function was called taking in two arguments, the environment in which the variable was to be placed in, and a table with the variables to be set.  The variable 'a' was set, along with the reset for the global table.


Or you will have to call the function so that the variables within the function don't get destroyed:
==Lexical Scoping==
In the last example you may have noticed that I said "the variable was also accessible by descendant environments".  This concept is called lexical scoping.


<pre>
{{Example|<syntaxhighlight lang="lua">
function myFunction() 
if true then --level 1
myVariable = 64
local a = 82.5
if true then --level 2
local b = 64
end
end
end
myFunction() -- the function is being called here
</syntaxhighlight>}}
print("myVariable is " .. myVariable)
 
</pre>
This is a simple example with two conditionals. If you recall, conditionals also have their own environment. Here is a snippet to prove this:


Local variables can keep variables within the scope of the function or environment it is declared in.  Variable environments can also be set with getfenv and setfenv.
{{Example|<syntaxhighlight lang="lua">
<pre>
if true then --level 1
function myFunction()
local a = 82.5
local myVariable = 64
if true then --level 2
local b = 64
end
print(b) --> nil
end
end
myFunction()
</syntaxhighlight>}}
print("myVariable is ", myVariable) --> myVariable is nil
 
</pre>
Its nil because variable b was confined to the scope of the second conditionalLexical scoping will allow one to do this:
This outputs nil because the word 'local' prevented the variable from being accessible outside of the function's environment even when the function was calledGlobal variables can be set easily by removing the word local, but for even better control over a variables scope, you can use setfenv.
 
<pre>
{{Example|<syntaxhighlight lang="lua">
function myFunction()
if true then --level 1
function myFunction2()
local a = 82.5
print(a)
if true then --level 2
end
print(a) --> 82.5
myFunction2()
local b = 64
print(a)
end
end
end
setfenv(myFunction, {a = 64,print=print, _G = unpack(_G)})
</syntaxhighlight>}}
myFunction()
print(a)
</pre>
This will output two values of 64, and will output one nil.  The variable's environment was set to the function 'myFunction', and therefore the variable was also accessible by descendant environments (myFunction2).  The setfenv function was called taking in two arguments, the environment in which the variable was to be placed in, and a table with the variables to be set.  The variable 'a' was set, along with the reset for the global table.


== See Also ==
Even though the second conditional has its own environment, because of lexical scoping, {{`|a}} was inherited.  Variables that are lexically scoped are called upvalues.


[[Variables]]
==See Also==


[http://wiki.garrysmod.com/wiki/?title=Basic_Lua#Scope GMod Wiki]
*[[Variables]]
*[http://www.lua.org/manual/5.1/manual.html#2.11 Lua 5.1 Reference Manual: Coroutines]
*[http://www.lua.org/pil/9.html Programming in Lua: Coroutines]


[[Category:Scripting Tutorials]]
[[Category:Scripting Tutorials]]

Latest revision as of 02:20, 27 April 2023

What is Scope?

Scope is a block of code in which variables are declared. for loops, while loops, repeat until loops, functions, if then, and do end chunks all create a new variable scope. For most of the following examples, the do end chunk will be used as a simple way of creating a variable.

Variables can be declared in two ways: local (with the local keyword), and global. Global variables are always in scope: no matter where you declare them, they are always accessible.

Example
function myFunction()
	myVariable = 64 --globally scoped
end

myFunction()

print("myVariable is " .. myVariable)

Output:
myVariable is 64


When myFunction was called, myVariable was set to 64. Since this variable is globally scoped, it could be accessed outside the function. This is why the output was "myVariable is 64". Take a look at this example using the local keyword to change the scope of a variable.

function myFunction()
	local myVariable = 64
end

myFunction()

print("myVariable is " .. myVariable) -->  myVariable is nil

"myVariable is nil" was outputted because myVariable was confined to myFunction's environment or its scope. Therefore, it was not able to access the value outside of that function.

Global variables can be set easily by removing the word local, but for even better control over a variables scope, you can use setfenv.

Example
function myFunction()
	function myFunction2()
		print(a)
	end
	myFunction2()
	print(a)
end
setfenv(myFunction, {a = 64,print=print})
myFunction()
print(a)

--[[
Output:
64
64
nil
]]


This will output two values of 64, and will output one nil. The variable's environment was set to the function 'myFunction', and therefore the variable was also accessible by descendant environments (myFunction2). The setfenv function was called taking in two arguments, the environment in which the variable was to be placed in, and a table with the variables to be set. The variable 'a' was set, along with the reset for the global table.

Lexical Scoping

In the last example you may have noticed that I said "the variable was also accessible by descendant environments". This concept is called lexical scoping.

Example
if true then --level 1
	local a = 82.5
	if true then --level 2
		local b = 64
	end
end


This is a simple example with two conditionals. If you recall, conditionals also have their own environment. Here is a snippet to prove this:

Example
if true then --level 1
	local a = 82.5
	if true then --level 2
		local b = 64
	end
	print(b) --> nil
end


Its nil because variable b was confined to the scope of the second conditional. Lexical scoping will allow one to do this:

Example
if true then --level 1
	local a = 82.5
	if true then --level 2
		print(a) --> 82.5
		local b = 64
	end
end


Even though the second conditional has its own environment, because of lexical scoping, a was inherited. Variables that are lexically scoped are called upvalues.

See Also