This multipart guide was made in collaboration with @severedskullz and @AstralGhost INDEX Lua Part 1: Strings and Terminology Lua Part 2: Operators, Tables, Statements and Loops TABLE OF CONTENTS Chapter 5: Operators Chapter 6: Tables Questions Chapter 7: Loops and Statements Questions REFERENCE PAGES http://www.tutorialspoint.com/lua/lua_standard_libraries_math_library.htm http://www.tutorialspoint.com/lua/lua_tables.htm http://lua.gts-stolberg.de/en/Tables.php If you have not read part 1. I suggest taking a look at it. If you have, than welcome to Part 2. In part 2 we will be focusing on tables, operators, statements and loops. Or the meat and potatoes of lua. So lets get started Also remember to use http://repl.it to follow along. So you can test the code your self and first hand witness each lesson in action. . CHAPTER 5: OPERATORS LUA has different type of operators; Arithmetic and Relational, Logical Arithmetic Operators Code: `+´ (addition), `-´ (subtraction), `*´ (multiplication), `/´ (division), and the unary `-´ (negation) With partial support for `^´ (exponentiation) Relational Operators Code: < > <= >= == ~= Relational operators always result in a value of TRUE or FALSE < : Less Than - True if the value before the operator is less than the second value. > : Greater Than - True if the value before the operator is greater than the second value. <= : Less Than or Equal To - Same as the Less Than operator, but also True if both values are equal. >= : Greater Than or Equal To - Same as the Greater Than operator, but also True if both values are equal. == : Equal To - True only if both values are equal to each other. ~= : Not Equal To - False if both values are equal to each other, otherwise True. When comparing values with different types, you must be careful: Remember that "0"==0 is false. Moreover, 2<15 is obviously true, but "2"<"15" is false (alphabetical order!). To avoid inconsistent results, Lua raises an error when you mix strings and numbers in an order comparison, such as 2<"15". Logical Operators Logical operators help create conditional statements in functions, to understand what that means first lets get a basic idea of each of the logical operators. The 3 logical operators are; Code: and, or, not and - requires all conditions to be true to result in a true result or - requires only a single condition to be true not - inverses the value. So if the statement is true, it will result in a false value. Now to get a better idea lets look at a code example Do not worry about the if else statement in the following piece of code. We will get more into that later. First lets look at "and" Code: a = 1 b = 2 c = 3 d = 4 if a > b and c < d then print("true") else print("false") end Now if you notice in the code 1 > 2 and 3 < 4. Obviously 1 is not greater than 2 - hence the statement is false. Using "And" allows us to create a condition which requires both conditions to be met to result in a true value. Lets look at "or" now. Code: a = 1 b = 2 c = 3 d = 4 if a > b or c < d then print("true") else print("false") end Here you will notice that the 2nd statement is true. Hence the final result of the logical operator will be true. Using the "Or" operator requires only a single statement to be true before it returns a true value. Now for sake of completion lets make them both false values Code: a = 1 b = 2 c = 3 d = 4 if a > b or c > d then print("true") else print("false") end As you will notice in this case both statements are false, hence it produces a false value. not - function simply causes the result to be opposite. For example lets look at a true statement and add "not" Code: a = 1 b = 2 c = 3 d = 4 if not (a < b and c < d) then print("true") else print("false") end Now as you can see 1 is less than 2, and 3 is less than 4. But because of not the result again ends up being false. If you have keen eyes you will also notice the statement is now in brackets - in order to properly perform the order of operations. . CHAPTER 6: TABLES TERMINOLOGY Tables - are objects which holds information generally on basic rows and columns based system. In LUA there is no limit to the amount of data added to a table, nor the type of information. You can house variables, functions, strings, and even other arrays. Tables in LUA use associative arrays. But before we get into that lets look at the tables. Classic Table Baseball Team Wins Code: Teams Wins Red Sox 2 Astros 3 Mets 9 LUA TABLE - Array Code: Baseball[1] = 2 Baseball[2] = 3 Baseball[3] = 9 LUA TABLE - Associative Array Code: Baseball["Red Sox"] = 2 Baseball["Astros"] = 3 Baseball["Mets"] = 9 As you can see the classic table you grew up with is not exactly the same as the Table we see when we look at LUA. No column names, row names, just pure unadulterated data. In the case of an array you can see each value is held by a numerical key [starting by default from 1 - though it can start with any number if defined so], and with an associative array a string. Though don't be fooled an associative array need not be a string key, it can be a numerical value or a variable also. PARTS OF A TABLE Before we go into making a table, lets look at the parts of one. Code: a[b] = c a = the current table identifier. Tables are anonymous and are not permanently attached to the identifier. They can be switched to any identifier at any time. But once no identifier is attached to the table, the table deletes it self. b = the key Notice it is enclosed by square brackets. The information inside the square bracket is the key value associated with the data. The key value can it self be any identifier, even a string. Note if a key is not assigned as in writing into a table directly - the table automatically assigns a numerical key which we will see a bit later. c = the data The data can be anything from a variable, string, function, or even another table, etc. CREATING AND SETTING UP TABLES Now that we know the parts of a table and the basic terminology involved. Lets first look at creating a table. For sake of time lets divide it into two main methods; simple and complex. Simple method Code: a = {} -- You first create the table. a[key] = data -- afterwards you assign keys and data accordingly In the simple method we first create a table and assign values to it. Complex method Code: complexTable = {"Auto Index 1" , "Index 2", "Index 3", [10] = "manual index 10", secretKey = "Mine is 'secretKey' "} print(complexTable[1]) In the complex method we not only create the table but assign values to it in one fell swoop. Yet a keen eye will notice that is not all we did. We also used different methods of assigning keys to that data. So lets take another look at keys. Data without an assigned key will automatically be assigned a key by lua in numerical order starting from one. ["bob"] = "dole" - Will assign the key bob to the value dole. You are free to use any number also even negatives. NESTED TABLES Now to finish off tables lets look at nested tables. As we started earlier nested tables are tables within tables. Lets look at a few examples. Code: someTable = {anotherTable = { yetAnotherTable = { } } } -- We now have 3 tables! Access them the same way you would normally. I used a keyed value so I would type this: Code: someTable.anotherTable.yetAnotherTable -- Would give me the third table. someTable["anotherTable"]["yetAnotherTable"] -- Same thing but with Array-like access. Assigning still works the same, but at a different level Code: someTable.anotherTable.aNewTable = {} -- We just created a new table inside anotherTable. "anotherTable" now has 2 tables: aNewTable and yetAnotherTable STRINGED KEYS AND NAMED FIELDS AND ACCESSING DATA Now that we know about how to create a table and what are nested tables. Let us look at accessing the data from the tables. As you may remember the simple method for placing data is essentially the same way to access the data. So if I wanted to access data for example from the table. Code: a = {} a["bob"] = 10 print[a["bob"]) -- Would result in 10 Even in the case of nested tables I would do same thing. Code: a = { b = { c = { "ten" } } } print(a["b"]["c"][1]) Now this part is where variable names and string names becomes very important. A variable and a string are 2 different things. If you remember from the previous part a ≠ "a" even though they can. They are not by default equal. One is a variable the other is a string. So lets take a look at an example Code: a = "bob" table = {} table[a] = 99 print(table[a]) -- You will get 99 print(table["a"]) -- You will get Nil This is because the interpreter will automatically exchange the variable a with its value bob. To pull the data. Or in other words it is actually "bob" which is assigned the data. The variable "a" points to the value "bob" which is passed in to the table index lookup which finally returns our value of 99 stored there. Now a stringed key is simply a "string" which is a key. But there are 2 methods to set-up a stringed key. one method is without quotes, the other is with quotes and square brackets. If you use quotes without square brackets, you created a string. A string it self cannot hold data, it is not a variable. So Code: a["This is valid"] -- Works a.This is valid -- Does not work. a.This_is_valid -- Works, but the key is set to "This_is_valid" Another thing to point is when using the simple method to define a string key, you cannot use spaces. If you want spaces for a string key you need to use quotes and brackets. You can access data more quickly by setting up a field name with dots. For example Code: a = { b = { c = {"hello"}}} print(a.b.c[1]) -- prints hello print(a["b"]["c"][1]) -- prints hello Code: a = { ["bob is cool"] = { c = { "hello"}}} print(a.bob is cool.c[1]) -- would not work because of the space. The correct method would be Code: print(a["bob is cool"].c[1]) SIZE OF ARRAY In some cases you may want to find the size of an array. Lua provides 2 functions table.getn() #table_name Examples Code: numb = { "one", "two", "three", "four" } print(table.getn(numb)) or Code: numb = { "one", "two", "three", "four" } print(#numb) These functions though simple only provide the table size of numerically indexed data and ignores stringed keys. For example Code: a = {"one", "two", "three", "four"} a["five"] = ten a["eleven"] = twelve print(#a) --> will result only in 4 The other main issue is it does not ignore nil values so it does not give an accurate representation in how much data is held with in the table. For example Code: a = {"one", "two", "three", "four"} a[8] = "Hello" print(#a) --> will result in 8 In this example it will show 8 values are in the array, even though there are only 5. To get an accurate representation in the amount of numerically indexed data in an array we use a for loop. Code: a = {"one", "two", "three", "four"} a[8] = "Hello" count = 0 for _ in pairs(a) do count = count + 1 end print(count) . BREAK TIME Now is a good time to take a break. You now have a fundamental knowledge of arrays and tables in LUA. Take some time to ponder what you learned and get ready for a quiz. Fair warning, some topics from the previous part are included to help you concrete the basics. Question 1: Since spaces do not work for the simple method of creating string keys, is there another character you can use besides space to make the simple string key method to work? Question 2: Using string.gsub() change the word "problem" to "answer". Assign a new value through a function. Code: a = {"Test problem 2"} print(a[1]) Question 3: Find the Mistake if any. Code: a.B.c = {"bob"} print(a.b.c[1]) Question 4: Find the mistake if any. Code: a = { b = c = {"bob"}}} print(a[c][1]) Question 5: Create a multi layered nested table. Where The first table contains 2 nested tables. And each nested within the tables contains 2 nested tables each. The last 4 nested tables should hold the values one, two , three, four respectively. Print the final nests and its values as proof. ANSWERS Answer 1: Underscore is one option. for example a["bob_is_cool"] Answer 2: Since we want to modify a[1] - we first need to assign a "new value" with a[1] than use a function to manipulate that value. Code: a = {"Test problem 2"} a[1] = string.gsub(a[1], "problem", "answer") print(a[1]) Answer 3: There are 2 mistakes in the code. Code: a = { b = { c = { } } } a.b.c = {"bob"} print(a.b.c[1]) The first mistake was the table was not initially defined. Hence did not even exist. The 2nd mistake is capitalization. b and B are not the same. Answer 4: in the print function the b and c are variables with no values. They are not the identifier of the key. Code: print(a["b"]["c"][1]) Answer 5: The identifiers do not matter - but the concept is easy once you understand how nested tables work. It becomes even more legible if you break each component into a separate line. Code: z = { a = { c = {"one"}, d = {"two"} }, b = { e = {"three"}, f ={"four"} } } print(z.a.c[1], z.a.d[1], z.b.e[1], z.b.f[1]) . CHAPTER 7: LOOPS AND STATEMENTS A statement is a set of instructions which occurs when a specific condition is met. Also each statement requires you to add an "end" to it. Which is very important, as it is a common cause of errors when you forget to do so. IF ELSE THEN (and ELSEIF) Essentially what this statement does is, first, it checks if the statement is true. If it is, then it does the first set of instructions. If the statement is false, it performs the 2nd set. One thing to keep in mind: each IF statement requires an end, and each function requires an end. If you use elseif - then it requires only 1 end ( not including the function's end ) - now all that just sounds complicated, so better just look at the example. Our first example would be what it would be like without else Code: a = 1 b = 2 c = 3 d = 4 if a > b then print("1 is less than 2") end if b > a then print(b.." is greater then "..a) end Since the statement is not true the first statement gives no result after which the next statement gets processed. If both statements were true, both statements get printed. What we need to learn is end essentially defines the end of that block of code. So what if we wanted a single result? Which is where "else" comes in. It will give one result or the other in sequential order. Code: a = 1 b = 2 c = 3 d = 4 if a > b then print("1 is less than 2") else print(b.." is greater then "..a) end Because the first statement was false - the 2nd result comes, but only one result will appear. What if we wanted to test multiple problems? We have elseif Code: a = 1 b = 2 c = 3 d = 4 if a > b then print("1 is less than 2") elseif b > c then print(b.." is greater than "..c) elseif c < d then print(c.." is less then "..d) end Since the first statement is false, it goes to the 2nd statement and since that is false it goes the the 3rd. Since the third is true it prints the result accordingly. WHILE \ DO LOOPS A while loop keeps continuing until a certain condition has been met. These are great ways to process arrays. The syntax of a while loop is Code: while condition do Let us take a look at an example Code: example = {"one", "two", "three", "four"} x=1 while x <= #example do print(example[x]) x = x + 1 end FOR \ DO LOOPS "FOR" loops give us a different type of control when it comes to loops. Especially as it focuses more on numbers. The syntax of a for loop is Code: for variable = beginning, finish, step do Code: for x = 1, 10, 1 do print(x) end Now lets break it down The starting number of the variable is 1, it must end at 10, and it increments the numbers by 1. Now what purpose might this serve? It allows a statement inside the FOR block to keep repeating for a specific number of times. For example say you wanted poison damage to be applied PUTTING IT TOGETHER Now lets make a simple function to look for "Bob" and perform an action when it is found Code: entityID = {entity1, entity2, entity3, entity4} entity1 = "Phil" entity2 = "Katrina" entity3 = "Jessica" entity4 = "Bob" for x = 1, #entityID, 1 do if entityID[x] == "Bob" then print("found") break end end Now in this block of code it will keep increasing one till the total number of values in the array entityID is met. Now we have another block statement using "IF" which will wait till the value equals bob. We use break to end that particular piece of the loop to allow the main block to continue. The loop then add one value to "x" and continue until it reaches the end of the array. Question: What can we quickly add if we also wanted to know the position of "Bob" in the array? Code: print("found in position "..x) . BREAK TIME Question 1: Find and print the size of the following table Code: a = {"one", "two", "three", "hundred", "dog", "cow"} Question 2: Print all the odd numbers upto 10 Question 3: Find the mistake in the code Code: if 1 > 2 print["true"] else print("false") Question 4: What kind of keys does using the # or table.getn() only return? and what keys do they not return? ANSWERS Answer 1: Code: a = {"one", "two", "three", "hundred", "dog", "cow"} print (#a) Answer 2: Code: for x = 1, 10, 2 do print(x) end Answer 3: Code: if 1 > 2 then print("true") else print("false") end "then" is missing after the condition the first print uses square brackets instead of round brackets end is missing Answer 4: Numerical, they do not return stringed keys. If you spot any errors just leave a message so we can get that fixed up.
nice lua tutorial man will this guide become more starbound related later? cos now its just lua basics...
While you wait - these two tutorials should be ample to get you started. By referencing vanilla code and going to the lua docs page you should be able to make some basic Lua items already.
awesome Might wanna add the second form of for loops? You used it in the tutorial but never explained it I dunno if it is usefull for starbound, but it is essential for normal coding.
Wait, we didn't add that? We talked about it quite a bit. I thought we added it.... Hmm. My proofreading skills suck. Also, I found this in the loop section: The 'function' being referred to there actually does stop when it finds "Bob" because there is a "break" in the if-statement when found. So you can remove this line. That was one of those things I found before the guide was posted then forgot about later and missed on my last proof-read.
guys actually lua is pretty similar to visual basic am i right? i dont use it much, i prefer c# for obvious reasons but i think vb is many similarities at the syntax
You are mixing things up here, Sir. lua actually is a scripting language and Visual basic is not. VB is a Programming language (not to be confused with VBScript). Scripting languages aren't meant to write programms in but can extend an existing programm to easyly add features or maintain stuff. C# is a programming language like java or python, which are used to design whole programms. Programming languages are way more powerfull but also more strict in syntax and less forgiving with variables & types. So switching from script to programming is much harder than the other way round. But yes, if you can code a single language, you basically just need to learn a new syntax and will be able to code in a new language ... they all work pretty much the same way.
i know man i am a c# programmer myself but there really can be similarities between script and programming languages. They work the same way but scriptiong languages are not compiled and can be interpreted by other programs differently (due to bugs or so - just like internet explorer is interpreting javascript not as firefox does). The syntax of scripting and programming languages may have similarities although the purpose is completely different. The syntax of lua reminds me of vb for example although there is no real connection between them cos lua is scripting and vb is programming.
I will look into adding this when I can break it down into simpler examples - but thanks for catching that.
Dont EVER use ipairs(). Just save yourself the headache. Unless you consistently make sure that youre table indexes are always consecutive whole numbers with no breaks then you are going to have what is called "Undefined Behaviour".