Introduction to Lua - Part III
This tutorial requires you to have a somewhat firm grasp on basic Lua concepts (variables, how to run Lua, etc...), for complete information please read Introduction to Lua and Introduction to Lua - Part II. Having basic programming experience is helpful as well.
Functions in Lua
So far we have covered what Lua is, basic variables, simple output, and looked at tables (Lua's only data structure). While Lua is a scripting language, there is no reason to approach programming in it in a top down manner. We can create functions for our subroutines to "modularize" our code better. Basic syntax is as follows:
function functionName (params) --code end
A couple of important notes, you do not have to return anything and there is no type declaration to a function (like in Python). Remember that Lua is dynamically typed and the language will take care of all of it when it runs. However, it may be helpful to provide checking to ensure no run time errors are generated from an ignorant user. For example:
print(type(varName))
This will print the type (there are 8: nil, boolean, userdata, number, table, string, function, thread) of the variable passed in. The observant among you will notice that function is one of the types of variables. You can assign functions to variables and all sorts of neat things that we will get to later on in this tutorial. However, it would be prudent to go over assignments in Lua and how they differ from other languages you may be familiar with:
a, b = 5, 6 --assign print(a) print(b)
Output:
Quote
5
6
6
Not what you were expecting I'm sure. This is an example of multiple assignment. It goes from left to right, so 'a' is 5 and 'b' is 6. In multiple assignment, Lua evaluates all values and then performs the assignment, so we can do stuff like this:
x = 7 y = 8 x, y = y, x --swap print(x) print(y)
Output:
Quote
8
7
7
This is particularly handy as C/C++ programmer will note that in order to swap two values in a similar manner we'd need to create a temp value to hold the first number swapped out. This concept applies for all types, we can even do it for tables:
a[i], a[j] = a[j], a[i] --swap table values 'i' and 'j'
We can now rewrite the bubble sort presented in Introduction to Lua, using this technique:
function bubbleSort(table)
--check to make sure the table has some items in it
if #table < 2 then
print("Table does not have enough data in it")
return
end
for i = 1, #table do --> array start to end
for j = 2, #table do
if table[j] < table[j-1] then -->switch
table[j-1], table[j] = table[j], table[j-1] -->NEW
end
end
end
return
end
--example usage
table = {1,10,5,6,7}
for i = 1, #table do
print(table[i])
end
bubbleSort(table)
print("\n")
for i = 1, #table do
print(table[i])
end
Output:
Quote
1
10
5
6
7
1
5
6
7
10
10
5
6
7
1
5
6
7
10
While we can see that this is more efficient/cleaner, without knowing what that means, it can certainly be considered confusing, even convoluted to an extent. One last note on this before moving on, Lua will check to see if the number of variables on the left match the number of assignments on the right. If there is less on the right, 'nil' will be provided for those variables that do not have an assignment. Be explicit!
--common mistake a,b,c = 0 print(a,b,c) --> 0 nil nil --should be a,b,c = 0,0,0 print(a,b,c) --> 0 0 0 correct
Keep it in Your Function!
Remember that we briefly discussed that Lua has two scopes of variables: global (by default) and local (denoted by 'local' in front of the variable's name). Local variables are local to the "block" that they are in:
--local variable example x = 10 --global local i = 1 --local to the chunk (i.e. this file) while i <= x do local x = i*2 --local to this while loop print(x) i = i + 1 end i = 19 -->reassign for purpose of next test if i > 20 then local x -->local to the if block x = 20 print(x + 2) -->22 (if i was > 20), change values to test else print(x) -->global 'x' end -->'end' denotes block
Output is omitted given the similarity to the next example, see below.
This principle is the same to the counter often initialized in a for loop in C++ style languages. Once that loop ends, the variable goes out of scope. Be careful in Lua as misscoping a variable could lead to an obscure bug. This concept applies to functions as well, adding a function to the above test:
--function declaration function output() local x = 55 print(x) end --local variable example x = 10 --global local i = 1 --local to the chunk (i.e. this file) while i <= x do local x = i*2 --local to this while loop print(x) i = i + 1 end i = 19 -->reassign for purpose of next test if i > 20 then local x -->local to the if block x = 20 print(x + 2) -->22 (if i was > 20), change values to test else print(x) -->global 'x' end -->'end' denotes block --function test output()
Output:
Quote
2
4
6
8
10
12
14
16
18
20
10
55
4
6
8
10
12
14
16
18
20
10
55
The best advice is to be explicit. Never let other programmers guess your intentions. Leave a comment, use local, etc... This transcends all languages. It is simply good programming practice.
Possibly the Coolest Thing You Have Ever Seen
This question gets asked a lot:
Quote
How can I return multiple values from a function???
The solution to the above question can be rather intricate, depending on the language. Passing by reference, calling multiple functions, and on and on it goes. In Lua, you can return as many values as you want! It's true! Consider the max number in a table finder snippet:
function findMax(a)
local mi = 1 --index of max value
local m = a[mi] --max value
for i, val in ipairs(a) do
if val > m then
mi = i
m = val
end
end
return m, mi --neat feature of lua, can return multiple values
end
--example usage
print(findMax({2,6,90,45,67,88,100})) -->100 7, max num and index location
Output:
Quote
100 7
We returned two values from the same function! I can hear the sound of rejoicing from your computer room. Now, if that wasn't cool enough, we can use the multiple assignment feature from earlier in this tutorial to assign values for later use:
function findMax(a)
local mi = 1 --index of max value
local m = a[mi] --max value
for i, val in ipairs(a) do
if val > m then
mi = i
m = val
end
end
return m, mi --neat feature of lua, can return multiple values
end
--example usage
firstVal, secondVal = findMax({2,6,90,45,67,88,100}) -->100 7, max num and index
print(firstVal.." "..secondVal)
Output is the same.
As previously discussed, that could get confusing, so put a comment or be explicit in your variable naming conventions, etc... The above (firstVal, secondVal) was enough to know which variable was assigned what. If we changed the order of return in the function, we'd have to change the assignment order. Keep that in mind. If there are not enough values returned from a function, 'nil' is provided for extraneous variables, Lua does this automatically.
Quit Playing With Your Function at the Table!
Another neat feature that you can use with function is the unkonwn or unlimited parameters. C programmers will find this syntax familiar:
--sum all the parameters together
function add(...)
local s = 0
for i, v in ipairs{...} do
s = s+ v
end
return s
end
print(add(3,4,25,12)) -->44
Output:
Quote
44
You've already seen a standard library function utilize this concept, print(). There are several other variations on this concept, but are out of the scope of this tutorial.
A Dive Into Functional Programming
One last item on functions: functions are first class values in Lua. This means they have the same rights as variable types like numbers and strings. Functions also have lexical scoping; this entails their ability to access variables within their enclosing functions. This can get quite complicated. Here is a relatively simple example:
--impractical example
a = {p = print} -->p refers to the print function
a.p("Hello World") -->calling p as print
print = math.sin -->the print function now refers to math.sin
a.p(print(1)) --> 0.841470
sin = a.p -->sin now refers to the print function
sin(10, 20) --> 10 20
Output:
Quote
Hello World
0.8414709848079
10 20
0.8414709848079
10 20
This is impractical because you would not want to rewrite a standard library function such as print(). (Well you may want to, but there's no reason.) I would consider it the anti reinventing the wheel syndrome. The point of the above is to illustrate, that in Lua, functions are anonymous, they do not have names. print is actually a variable that holds the function, hence our ability to reassign it. Horribly confused on that last part? I'll be covering more advanced functional programming concepts Lua has in future tutorials. Consider your whistle thoroughly whetted.
Hopefully you found this tutorial both informative and interesting. Part IV will probably contain a roundup of anything "basic" I haven't covered yet. Happy Coding!
--KYA
0 Comments On This Entry
← January 2022 →
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 | 31 |
Tags
My Blog Links
Recent Entries
Recent Comments
Search My Blog
21 user(s) viewing
21 Guests
0 member(s)
0 anonymous member(s)
0 member(s)
0 anonymous member(s)



Leave Comment









|