First Draft, following sorta closely to the original. |
No edit summary |
||
(2 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
{{Notice/Warning | {{Notice/Warning | ||
|content='''This page has been discarded.'''<br> | |||
No more work will be done on this page. | |||
}} | }} | ||
Line 63: | Line 64: | ||
|name=script-checker.lua | |name=script-checker.lua | ||
}} | }} | ||
Watch out for all other instances of <code>c</code> throughout the rest of the document, it may interfere with other scripts. ;) | We'll get more into variable scopes later. Watch out for all other instances of <code>c</code> throughout the rest of the document, it may interfere with other scripts. ;) | ||
=== Valid Names === | === Valid Names === | ||
Variable names... | Variable names... | ||
Line 114: | Line 115: | ||
Strings can be modified using the [https://www.lua.org/manual/5.2/manual.html#6.4 String standard library], accessible using either the <code>string</code> global or by using the methods on strings themselves. | Strings can be modified using the [https://www.lua.org/manual/5.2/manual.html#6.4 String standard library], accessible using either the <code>string</code> global or by using the methods on strings themselves. | ||
When defining a string in code, make sure to use <code>\n</code> in place of linebreaks within the string. Using real line breaks instead of <code>\n</code> will result in a syntax error. | |||
You may also need to escape single/double quotes in case the character you want to use is already used to wrap the string. In that case, just put a backslash (<code>\</code>) in front of the character to escape it (for example, <code>"\""</code> is the same as <code>'"'</code>). | |||
====Literal Strings==== | ====Literal Strings==== | ||
Strings, when surrounded by double brackets (<code>[[]]</code>), take characters at face value. These are called literal strings and can be used to make a string span multiple lines. | Strings, when surrounded by double brackets (<code>[[]]</code>), take characters at face value. These are called literal strings and can be used to make a string span multiple lines. | ||
{{Script | |||
|script=print("Hello, World!") --> Hello, World! | |||
print("\"Line 1\" | |||
'Line 2'") -- ERROR! unfinished string near '""Line 1"' | |||
print("\"Line 1\"\n'Line 2'") --> "Line 1" | |||
-- 'Line 2' | |||
print([["Line 1" | |||
'Line 2']]) --> "Line 1" | |||
-- 'Line 2' | |||
}} | |||
==={{Type|nil}}=== | ==={{Type|nil}}=== | ||
Unlike other types, {{Type|nil}} is the ''absence'' of a value. This is what's returned when you try to use a variable not defined yet. | Unlike other types, {{Type|nil}} is the ''absence'' of a value. This is what's returned when you try to use a variable not defined yet. | ||
Line 129: | Line 143: | ||
local a = "Hello, World!" | local a = "Hello, World!" | ||
print(string.sub(a, 2, 5)) -- ERROR! attempt to index a nil value (global 'string')}} | print(string.sub(a, 2, 5)) -- ERROR! attempt to index a nil value (global 'string')}} | ||
==={{Type|table}}=== | |||
Tables are where things start to get more complex. Instead of containing ''one'' object, tables can store ''many'' objects in multiple different ways. | |||
For instance, a table can store a sequence of objects. This is commonly called an array. Arrays start at an index of one and continue counting up for each item added to the table. | |||
However, you don't ''just'' have to use numbers as indices. You can use any basic object (boolean, number, string, nil) you want! Doing so makes what's commonly called a dictionary, the indices called keys and the values called values. | |||
{{Script | |||
|script=local a = {"Hello,", "World!"} | |||
print(a[1]) --> Hello, | |||
a["diamond"] = true | |||
print(a.diamond) --> true -- Doing something like a.diamond is the same as doing a["diamond"] | |||
local b = { | |||
[c] = true, -- I hope you remember what c is! | |||
[true] = 56, | |||
[5<3] = b or c -- Expressions can be used as keys and/or values. In this case, (5<3) comes out to true and (c and d) comes out to 10 since d is nil and global c is still 10. | |||
["foo"] = "bar" | |||
xyz = "abc" -- String keys can be removed from their brackets and quotes as long as they follow the variable name rules above. | |||
} | |||
print(b[b.foo == "bar"]) --> 56 -- Expressions can also be used to index a table. | |||
}} | |||
Sometimes, you may want to go over all items within a table. This can be done with a [[#Loops|for loop]]. |
Latest revision as of 03:29, 7 October 2024
This page has been discarded.
No more work will be done on this page.
The Interpreter
The interpreter is just the thing that runs your Lua code. In Figura's case, it's a custom version of LuaJ, an interpreter written in Java.
A Lua interpreter reads each line sequentially, executing each line before moving on to the next one. This makes it hard to break away from the sequence without breaking the program entirely for something like a sleep call.
Comments
Comments are used to tell the interpreter to ignore a part of the code, either because it's for human programmers to see or it's a piece of code that should not be executed.
Short comments, comments that only affect one line, start with --
. From the two dashes to the end of the line, code will be ignored.
--This is a comment.
local x = 2 -- Everything after the two dashes will be ignored.
-- local y = 3 -- The preceding code will not run because it's part of a comment.
-- This is useful in case you need to document your code for future programmers or you need to stop code from running without removing it from the script.
Long Comments
Long comments, comments that can go over multiple lines, come in the form of --[[ ]]
. Everything between the two brackets is commented and, thus, ignored by the interpreter.
--[[
This is a block comment. None of the
lines within the comment will be executed
until the final bracket.
--]] -- Sometimes programmers will put two dashes before the end of block comments. This is not required but looks nice.
local z = 5 -- You can use both types of comments within the same script.
--[[
Block comments are useful for long
explanations of code or for ignoring
large swaths of code.
]]
Variables
Think of variables as a bunch of boxes. Each variable is one box, a label printed on it with an object (or, in some cases, a few) stored inside.
To put something inside a variable, you'll want to set it equal to that something. For example...
local a = 247 -- Make a new local variable "a" and set the value within to be the number 247.
local b = "Hello, World!" -- Make a new local variable "b" and set the value within to be the string "Hello, World!"
c = 10 -- Make a new *global* variable "c" and set the value within to be the number 10.
The last variable, c
, is a global variable. This means that it can be used anywhere within the Lua environment. While this may seem like a good thing at first, there are many cases where this may not be a thing you want. For example, let's see how a system like below, assuming each script is run in sequence in the same environment, would fare with global variables
script = 1
return function() return script end
script = 2
return function() return script end
script = 3
return function() return script end
print(require("test-script-1")()) --> 3
print(require("test-script-2")()) --> 3
print(require("test-script-3")()) --> 3
We'll get more into variable scopes later. Watch out for all other instances of c
throughout the rest of the document, it may interfere with other scripts. ;)
Valid Names
Variable names...
- Can only use alphanumeric characters and
_
- Must not start with a number.
- Cannot be the same as a Lua keyword (
and
,or
,if
,while
, etc.)
For instance...
local a -- ✅ Valid
local _b -- ✅ Valid
local aBc123 -- ✅ Valid
local 123abc -- ❌ Invalid; Variable names cannot start with a number.
local foo-bar -- ❌ Invalid; Variable names can only use alphanumeric characters.
local and -- ❌ Invalid; Variable names cannot be the same as a Lua keyword.
local local -- ❌ Invalid; Variable names cannot be the same as a Lua keyword.
Declaring Without Setting
In some cases, you may want to declare a local variable without setting its value. This can be done by just writing local variableName
without adding a =
local a -- a is now initialized as a local variable with no value.
print(a) --> nil
a = 3 -- Variables already declared as locals do not need to be marked as local again.
print(a) --> 3
Types
A type is any sort of object, whether it be a few words, a number, a true/false value, etc.
boolean
Booleans hold one of two values: true
or false
.
These are typically returned when a relational operator (==
, >
, <=
, etc.) or a boolean operator (not
, and
, etc.) is used.
print(true) --> true
print(5 > 3) --> true
print(10 <= 6) --> false
print(true and false) --> false
number
Numbers are numbers, either integer or decimal.
Numbers are typically returned when an arithmetic operator (+
, -
, *
, /
, etc.) is used.
print(5) --> 5
print(5 + 2) --> 7
print(5 * 2) --> 10
print(5 / 2) --> 2.5
string
Strings are sequences of characters, most notably text. When defined in code, strings must be wrapped in either quotes ("
) or single quotes ('
).
Strings can be modified using the String standard library, accessible using either the string
global or by using the methods on strings themselves.
When defining a string in code, make sure to use \n
in place of linebreaks within the string. Using real line breaks instead of \n
will result in a syntax error.
You may also need to escape single/double quotes in case the character you want to use is already used to wrap the string. In that case, just put a backslash (\
) in front of the character to escape it (for example, "\""
is the same as '"'
).
Literal Strings
Strings, when surrounded by double brackets ([[]]
), take characters at face value. These are called literal strings and can be used to make a string span multiple lines.
print("Hello, World!") --> Hello, World!
print("\"Line 1\"
'Line 2'") -- ERROR! unfinished string near '""Line 1"'
print("\"Line 1\"\n'Line 2'") --> "Line 1"
-- 'Line 2'
print([["Line 1"
'Line 2']]) --> "Line 1"
-- 'Line 2'
nil
Unlike other types, nil is the absence of a value. This is what's returned when you try to use a variable not defined yet.
print(a) --> nil
print(b) --> nil
print(c) --> 10
-- Oh, there's our lovely little global "c" again! Didn't expect that, did you?
Scripts can at best return/display unwanted values and at worst error if a nil pops up where it shouldn't.
string = nil
local a = "Hello, World!"
print(string.sub(a, 2, 5)) -- ERROR! attempt to index a nil value (global 'string')
table
Tables are where things start to get more complex. Instead of containing one object, tables can store many objects in multiple different ways.
For instance, a table can store a sequence of objects. This is commonly called an array. Arrays start at an index of one and continue counting up for each item added to the table.
However, you don't just have to use numbers as indices. You can use any basic object (boolean, number, string, nil) you want! Doing so makes what's commonly called a dictionary, the indices called keys and the values called values.
local a = {"Hello,", "World!"}
print(a[1]) --> Hello,
a["diamond"] = true
print(a.diamond) --> true -- Doing something like a.diamond is the same as doing a["diamond"]
local b = {
[c] = true, -- I hope you remember what c is!
[true] = 56,
[5<3] = b or c -- Expressions can be used as keys and/or values. In this case, (5<3) comes out to true and (c and d) comes out to 10 since d is nil and global c is still 10.
["foo"] = "bar"
xyz = "abc" -- String keys can be removed from their brackets and quotes as long as they follow the variable name rules above.
}
print(b[b.foo == "bar"]) --> 56 -- Expressions can also be used to index a table.
Sometimes, you may want to go over all items within a table. This can be done with a for loop.