Advertise with Googlier.comLÖVE • Community Blogs - local
http://blogs.love2d.org/blog-terms/local
enScope within Lua
http://blogs.love2d.org/content/scope-within-lua
<div class="field field-name-field-blog-term field-type-taxonomy-term-reference field-label-inline clearfix"><h3 class="field-label">Blog Terms: </h3><ul class="links inline"><li class="taxonomy-term-reference-0"><a href="/blog-terms/lua">lua</a></li><li class="taxonomy-term-reference-1"><a href="/blog-terms/scope">scope</a></li><li class="taxonomy-term-reference-2"><a href="/blog-terms/global">global</a></li><li class="taxonomy-term-reference-3"><a href="/blog-terms/local">local</a></li></ul></div><div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>Far too often, while opening up a LÖVE file that someone posts on the forums, I see the
telltale signs of someone who does not understand the concept of scope. In their <code>player.lua</code>
file, they will be referring directly to some variables inside their <code>wall.lua</code> file,
which itself refers directly to some tables within the <code>main.lua</code> file.</p>
<p><!--break-->
Granted, there are some instances when polluting the global scope has a few benefits, but
you need to truly understand what it means before you can safely do so.</p>
<h2>About Me</h2>
<p>My name is Michael Kosler, and I'm a college student currently attending Texas A&M University, earning a bachelor's in Computer Science. I previously got a BA in Mathematics from Texas A&M University, and taught high school mathematics for about four months (couldn't even last a year :)). I'm hoping to break into the game industry professionally, and have been using Lua and LÖVE since 2011 to help build out my online portfolio.</p>
<h2>What is scope?</h2>
<p>Ripped from Wikipedia:</p>
<blockquote>
<p>In computer programming, a <strong>scope</strong> is a context within a computer program in which a variable name
or other identifier is valid and can be used, or within which a declaration has effect.</p>
</blockquote>
<p>While Wikipedia often gets the definition technically right, it also assumes you probably know
what scope is before you begin reading up on scope - a backwards proposition.</p>
<p>Scope, in the most general case, can be distilled down to one question: "Who knows I exist?"
This is an important question to ask in programming, because rarely does a program not
need to communicate with either other programs or other parts of itself. If you share
everything, then you might end up clashing with other parts of your program that need
similarly named variables.</p>
<h3>Globe Trekking</h3>
<p>The global scope is probably the simplest to understand. If I have a variable within the
global scope, then it is visible to the entire program. For example, consider two files:
<code>a.lua</code>, and <code>b.lua</code>.</p>
<p><strong><code>a.lua</code></strong></p>
<pre class="brush: lua">
-- x is defined in the global scope
x = 10
-- foo is defined in the global scope
function foo()
-- Since x is global, the function foo can refer to it
x = x + 5
print(x)
end
</pre>
<p><strong><code>b.lua</code></strong></p>
<pre class="brush: lua">
-- Bring the global scope from a.lua into b.lua
require 'a'
-- bar is defined in the global scope
function bar()
-- This x is still referring to the x we created in a.lua
x = x + 10
foo()
end
bar()
</pre>
<p>Running <code>b.lua</code> prints <code>25</code> onto the screen.</p>
<h3>I only buy Local Scope</h3>
<p>Local scope refers to pretty much all other situations of scoping. Generally, however,
to be in the local scope usually means that a variable is visible only to those other
variables that share the same scope. I will get to some examples on what local scope
looks like in code in a bit, but first I have to steer you away from a common problem.</p>
<p>If you are familiar with other programming languages, then this so far
has felt fairly familiar to you. Local scope, however, is where Lua starts
acting differently. Consider the following program:</p>
<pre class="brush: lua">
x = 10
function foo()
y = 20
end
function bar()
print(x, y)
end
foo()
bar()
</pre>
<p>In most other languages, this will give you an error. Why? Because in most
other languages, the variable <code>y</code>, defined within the function <code>foo</code>, is local
to that function, so when <code>bar</code> tries to print <code>y</code>, it has no understanding as
to what <code>y</code> is, and balks.</p>
<p>Lua, on the other hands, happily prints <code>10, 20</code>. Why? Because, in Lua, all variables
are, by default, global. Why would it do that? Ask
<a href="http://en.wikipedia.org/wiki/Roberto_Ierusalimschy">Dr. Ierusalimschy</a>. All we care about is
how we take advantage of local scoping.</p>
<p>Turns out its fairly easy: just append <code>local</code> to any variable that you wish that be inside
its local scope. Given that, let us fix the above code snippet to work like other programming
languages:</p>
<pre class="brush: lua">
x = 10
function foo()
local y = 20
end
function bar()
print(x, y)
end
foo()
bar()
</pre>
<p>Now, while this does not quite give us the error we would get in many other programming
languages, Lua prints <code>10, nil</code>, showing that <code>y</code> has no current meaning within the
scope of <code>bar</code>.</p>
<p>We can extend this idea of local scope between files as well. Suppose I have three files:</p>
<p><strong><code>player.lua</code></strong></p>
<pre class="brush: lua">
-- some other player functions
function draw(o)
love.graphics.setColor(o.color)
love.graphics.rectangle('fill', o.x, o.y, o.width, o.height)
end
</pre>
<p><strong><code>enemy.lua</code></strong></p>
<pre class="brush: lua">
-- some other enemy functions
function draw(o)
love.graphics.setColor(o.color)
love.graphics.circle('fill', o.x, o.y, o.radius)
end
</pre>
<p><strong><code>main.lua</code></strong></p>
<pre class="brush: lua">
require 'player'
require 'enemy'
local p = {
x = 10,
y = 10,
width = 20,
height = 50,
color = { 0, 255, 0 },
}
local e = {
x = 50,
y = 50,
radius = 15,
color = { 255, 0, 0 },
}
function love.draw()
-- Which one is which?
draw(p)
draw(e)
end
</pre>
<p>Clearly, I want different functions for drawing my player and my enemies. But, both the <code>draw</code>
function in <code>player.lua</code> and the <code>draw</code> function in <code>enemy.lua</code> pollute the global scope. So,
which draw was used? It actually depends on the order of the <code>require</code> statements, so in our case,
the <code>draw</code> in <code>enemy.lua</code> is the <code>draw</code> within the <code>main.lua</code>, so we get an error when we call
<code>draw(p)</code>, since <code>p</code> does not have <code>radius</code>.</p>
<p>The fix is fairly easy:</p>
<p><strong><code>player.lua</code></strong></p>
<pre class="brush: lua">
-- declare draw as local
local function draw(o)
love.graphics.setColor(o.color)
love.graphics.rectangle('fill', o.x, o.y, o.width, o.height)
end
-- return the local version of draw
return draw
</pre>
<p><strong><code>enemy.lua</code></strong></p>
<pre class="brush: lua">
-- declare draw as local
local function draw(o)
love.graphics.setColor(o.color)
love.graphics.circle('fill', o.x, o.y, o.radius)
end
return draw
</pre>
<p><strong><code>main.lua</code></strong></p>
<pre class="brush: lua">
-- Assign the return value of the two files to variables
local playerDraw = require 'player'
local enemyDraw = require 'enemy'
local p = {
x = 10,
y = 10,
width = 20,
height = 50,
color = { 0, 255, 0 },
}
local e = {
x = 50,
y = 50,
radius = 15,
color = { 255, 0, 0 },
}
function love.draw()
playerDraw(p)
enemyDraw(e)
end
</pre>
<h2>Why should I care?</h2>
<p>Think of scope as a directory or folder inside your computer. If you exclusively use the global
scope, then your computer has simple one directory, with all files shoved inside. In this
flat structure, anytime you attempt to save a new file, you would have to be on guard against
accidentally overwriting a previously saved file. Luckily, most modern operating systems
warn you before you accidentally save over some previous work. Lua, and most other
programming languages, do not give you that extra level of protection.</p>
<h2>What are you leaving out?</h2>
<p>Lua provides quite a few interesting tricks to meddle with the scope of the language. If you
are interested, here are a few advanced topics on scope within Lua:</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scoping_and_dynamic_scoping">Lexical scoping</a></li>
<li><a href="http://www.lua.org/pil/6.1.html">Closures</a></li>
<li><a href="http://www.lua.org/pil/8.1.html">The <code>require</code> function</a></li>
<li><a href="http://www.lua.org/pil/14.html">The Environment</a> <em>NOTE: as of Lua 5.2, this topic has changed significantly</em></li>
</ul>
</div></div></div><div class="field field-name-field-addthiswidget field-type-addthis field-label-hidden"><div class="field-items"><div class="field-item even"><div class="addthis_toolbox addthis_default_style addthis_32x32_style " addthis:title="" addthis:url="http://blogs.love2d.org/content/scope-within-lua"><a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_google_plusone_share"></a>
<a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_facebook"></a>
<a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_hackernews"></a>
<a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_reddit"></a>
<a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_twitter"></a>
<a href="http://www.addthis.com/bookmark.php?v=300" class="addthis_button_"></a>
</div>
</div></div></div>Wed, 13 Mar 2013 17:14:30 +0000MarekkPie19 at http://blogs.love2d.orghttp://blogs.love2d.org/content/scope-within-lua#comments