var = "hello"The preceding would print the word "string".
print(type(var))
#!/usr/bin/luaThe preceding prints out the following, which pretty much proves all that's been said in this section:
a = 1 -- this is a number
b = 10 -- this is a number
c = "100" --[[ this is a string representation
of a number ]]
print ("\nNumber below...")
print(a)
print(type(a))
print ("\nNumber below...")
print(b)
print(type(b))
print ("\nString below...")
print(c)
print(type(c))
print ("\nNumber + number below...")
print(a+b)
print(type(a+b))
print ("\nNumber + string below...")
print(b+c)
print(type(b+c))
print ("\nNumber concatted to string below...")
print(b..c)
print(type(a..c))
slitt@mydesk:~$ ./test.lua
Number below...
1
number
Number below...
10
number
String below...
100
string
Number + number below...
11
number
Number + string below...
110
number
Number concatted to string below...
10100
string
slitt@mydesk:~$
first="Steve" -- string, value "Steve"In the Numbers section you learned that the concatination operator is .. and that Lua converts "3004" to a number if it's used in a numeric expression. There's a function called tostring() that converts its argument to a string. This is useful in print statements when you're not sure whether something will be a string or nil. Therefore it's especially useful in diagnostic prints.
last="Litt" -- string, value "Litt"
whole=first .. last -- string, value "SteveLitt"
whole=first .. " " .. last -- string, value "Steve Litt"
#!/usr/bin/luaThe preceding code produces the following output:
price_earnings_ratio = 15.521825348912
company = "Troubleshooters.Com"
mystring = string.format("The price to earnings ratio of %s is %f.",
company, price_earnings_ratio)
print(mystring)
mystring = string.format("The price to earnings ratio of %s is %.2f.",
company, price_earnings_ratio)
print(mystring)
mystring = string.format("The price to earnings ratio of %s is %8.2f.",
company, price_earnings_ratio)
print(mystring)
mystring = string.format("The price to earnings ratio of %s is %08.2f.",
company, price_earnings_ratio)
print(mystring)
mystring = string.format("The price to earnings ratio of %s is %03.2f.",
company, price_earnings_ratio)
print(mystring)
slitt@mydesk:~$ ./test.luaYou can see that the number you put between the % and the f controls the formatting of the number (or string or anything else). For instance, 8.2 means use two places after the decimal point, but have the whole number take up exactly 8 spaces including the decimal point. The last example in the preceding code shows that if doing so would cut significant digits off the whole part of the number, then it print the number using more than 8 spaces. Here's a brief and incomplete list of substitution characters:
The price to earnings ratio of Troubleshooters.Com is 15.521825.
The price to earnings ratio of Troubleshooters.Com is 15.52.
The price to earnings ratio of Troubleshooters.Com is 15.52.
The price to earnings ratio of Troubleshooters.Com is 00015.52.
The price to earnings ratio of Troubleshooters.Com is 15.52.
slitt@mydesk:~$
%s |
string |
|
%e or %E |
|
Scientific notation |
|
%d |
integer (signed decimal) |
%o | octal (signed) |
|||
%f |
floating point |
%u | unsigned decimal |
|||
%c | character (use the ascii value) |
%x or %X |
unsigned hex |
mystring="123456789"Output looks as expected:
print(string.sub(mystring, 1, 3)) -- print 1st 3 characters
print(string.sub(mystring, -3)) -- print last 3 characters
print(string.sub(mystring, 2)) -- eliminate first character
print(string.sub(mystring, 4, -4)) -- eliminate the first 3 and last 3 chars
slitt@mydesk:~$ ./test.luaRemember, you use string.sub() to get substrings by position. To get them with matching, you use string.match(), string.find(), or string.gsub(). string.gsub() actually changes strings, and can transfer found strings to the replace string just like in Perl.
123
789
23456789
456
slitt@mydesk:~$
local string1 -- Declare it local but don't assign. It's nilYou might wonder why you'd ever want to assign nil to a variable.
local string2 = "hi" -- Not nil
string2 = nil -- It's as if nothing had ever been assigned to it
if not myvarOr this:
print("ERROR: myvar is nil, aborting!")
os.exit(1)
end
assert(myvar, "ERROR: myvar is nil, aborting!")Or you can use short circuit logic available in C, Perl and many other languages:
print(string.format("Myvar=>%s<",myvar or "nil value"))The more generic way to do the preceding is this:
print(string.format("Myvar=>%s<",tostring(myvar)))The preceding is better because if myvar happened to be a number or boolean it would print the number or either true or false. If myvar were a table it would print the table address, and if it were a function it would print the function address. In other words, it would not abort, which is often what you want, especially in debugging.
myvar = true -- myvar is trueYou test a boolean by simply naming the variable. For instance, let's say you have a boolean called should_continue. You could decide whether to skip over code in a loop as shown in the following pseudocode:
myvar = false -- myvar is false
myvar = 2 < 3 -- myvar is true
myvar = 2 > 3 -- myvar is false
should_continue = trueYou can put together booleans with and, or and the like:
while should_continue do
whatever()
if should_continue then
do_work_done_only_when_not_done()
should_continue = determine_whether_to_continue()
end
end
if should_continue and foundRemember, only boolean false and nil test false -- everything else tests true.
whatever()
end
if found or first_time
whichever()
end
mytable = {"one", "two", "three"} -- integer indexed keys starting at 1 mytable = {s="Sam, a="Al", d2="Don"} -- Indexed by random strings -- But not numbers mytable = {} -- Empty tableYou set or add table key/value elements like this:
mytable[numbervar] = value -- Key is a numberYou can also add with table.insert(), which has a two and three argument variety:
mytable["stringvar"] = value -- Key is a string
mytable.stringvar = value -- Exactly the same as above
CAUTION!
Do not rely on things like table.maxn(), #tablename and the like for
getting a table's number of elements or its "end". Don't assume a table
is sorted. table.maxn() and #tablename work only if you make sure all
entries have integer keys and the keys start at 1 and end at, let's say
20, and there are no nil values between 1 and 20. If that's too much to
assume, and it probably is, then don't assume it.This is not a problem because Lua gives you many ways to iterate all elements of a table, so there's little reason you need the highest numerical value. And even if you do, there are ways an application programmer can handle that. This will be discussed more on the Lua Tables page of this subsite, but I just want to say here this is not much of a limitation at all, as long as you make no assumptions. |
#!/usr/bin/luaAs you can guess, it prints out "Hello World". Look what happened. We made a function with no name, and assigned it to a variable called hello. A function is just another piece of data you can assign all over the place. Watch this:
hello = function() print("Hello World") end
hello()
#!/usr/bin/luaHere's the result:
hello = function() print("Hello World") end -- assign a function to hello
hello() -- execute that function
goodbye = "See ya later" -- goodbye is a string
print(goodbye) -- print the string
goodbye = hello -- assign the hello function to goodbye
goodbye() -- run the new goodbye as a function
slitt@mydesk:~$ ./test.luaA function is just a piece of data. This is SUCH a powerful feature, making complex tasks simple. You can pass functions as arguments to functions, pass them back as return values, assign them to variables, and use them as elements of tables. Consider the following:
Hello World
See ya later
Hello World
slitt@mydesk:~$
#!/usr/bin/luaResults:
mypoint={x=3, y=9, show=function(tab) print(string.format("x=%d,y=%d",tab.x,tab.y)) end}
mypoint.show(mypoint)
slitt@mydesk:~$ ./test.luaWhat happened there? You created table mypoint with three keys: x, y and show. The show key was assigned a value that was a function. Hey, that's fair, functions are data. If the above is too ugly for you, do this:
x=3,y=9
slitt@mydesk:~$
#!/usr/bin/luaSame thing, except now you're creating the show key after the fact, not during the declaration of mypoint. Consider what you'd have if you added mypoint.setx, mypoint.sety, mypoint.getx, and mypoint.gety. Data and functions all wrapped into one. Wouldn't that be kind of like an object? That would be the most primative OOP like idiom available in Lua, but Lua can get A LOT more OOP than that. See the Lua OOP page of this subsite.
mypoint={x=3, y=9}
mypoint.show=function(tab) print(string.format("x=%d,y=%d",tab.x,tab.y)) end
mypoint.show(mypoint)
mypoint.show(mypoint)Is it just me, or is that redundant and kind of stupid? No problem, you can use Lua syntactic sugar and change the dot to a colon, and then remove the redundant mypoint argument:
mypoint.show(mypoint) -- Shows x and ySo in other words, objectname.methodname(objectname) is the same as objectname:methodname().
mypoint:show() -- Does EXACTLY the same thing the same way
tablename.functionname()
NOTE
Lua purists will flame me to death over saying Lua has OOP, because technically that's not true -- it has tables with functions inside of them. And it has metatables to implement something just like OOP inheritance and something very similar to polymorphism and even operator overloading. But don't call it OOP :-) |
functname = function(args) do_something() endI could have written that more simply like this:
function functname(args) do_something() endOr, in the case of a function in a table (or object :-))
function tablename.functname(args) do_anotherthing() endAlso, the syntactic sugar version works correctly during recursion, which the other version doesn't do automatically. The reason I introduced the other version first was to demonstrate that functions are just data.
function whichbigger(num1, num2)Arguments to functions are treated like local variables visible only inside the function but be careful, tables are passed by reference so any changes to table arguments inside the function affect the table outside the function. If you want a variable local to the function, add the word "local" as seen on the second line of the preceding function. Local variables are local to their enclosing block, which could be a loop, if statement, or even a small block deliberately made with do and end to make a tiny scope.
local rtrn
if num1 > num2 then
rtrn = 1
elseif num1 < num2 then
rtrn = -1
elseif num1 == num2 then
rtrn = 0
else --internal error condition
print("FATAL internal error: neither bigger, smaller or same")
os.exit(1)
end
local age = 99You can declare a local with or without an initializer. If without, its value is nil. To find the scope of a local, go down from the local's declaration until you find the first end , elseif or until keyword. The local goes out of scope there. local's scope. Then go back up to the keyword matched by the end, elseif or until keyword. That will probably be a then, do, or elseif. Note that you might think of it as an if or while, but those conditionals are terminated by then and do respectively, and the code they run is terminated by an end, elseif or until.
local height
height = "7 feet, 7 inches"
[ Troubleshooters.com| Code Corner | Email Steve Litt ]
Copyright (C) 2011 by Steve Litt --Legal