Some lua tricks you may not have known...
#21
Posted 11 September 2012 - 06:34 AM
#22
Posted 11 September 2012 - 07:09 AM
--initialize a table like an array; lua will assign numeric keys starting with 1 local myArray={"cherries", "apples", "potatoes", "grapes", } --use the # prefix operator to get the size of the array print("myArray has "..#myArray.." items.") --[[outputs : myArray has 4 items --]] --you can use this to iterate over the array function printArray(array) for i=1,#myArray do print(i..": "..myArray[i]) end end printArray(myArray) --[[outputs 1: cherries 2: apples 3: grapes --]] --they're still really hashmaps, so you can add arbitrary members too... myArray.foo="bar" --...but those non-numbered members are ignored when treating it like an array print("myArray STILL has "..#myArray.." items.") --outputs: "myArray STILL has 4 items") --the table api, native to lua, provides some methods to help as well. You can remove items from the array.. table.remove(myArray,3) printArray(myArray) --[[ outputs 1: cherries 2: apples 3: grapes --]] --...or insert items table.insert(myArray,2,"bananas") printArray(myArray) --[[ outputs 1: cherries 2: bananas 3: apples 4: grapes --]] --you can even sort them! table.sort(myArray) printArray(myArray) --[[outputs: 1: apples 2: bananas 3: cherries 4: grapes --]] --though note, for this version of sort to work without errors, your array must contain all strings or all numbers. table.insert(myArray,4,9001) --calling table.sort(myArray) now would throw an error "attempt to compare string with number" --however, mixed arrays, or even arrays of tables, can be sorted with a custom compare function! function compareMixed(a,:D/>/> --convert both to strings first, then compare return tostring(a)<tostring(:)/>/> end --pass the function (WITHOUT ()s, just the name, like a variable!) to sort as 2nd parameter table.sort(myArray,compareMixed) printArray(myArray) --[[ outputs: 1: 9001 2: apples 3: bananas 4: cherries 5: grapes --]]
hope this helps />
#23
Posted 11 September 2012 - 03:50 PM
Kingdaro, on 20 August 2012 - 09:51 AM, said:
Note that this is not a lua tutorial and is intended for intermediate to advanced lua users.
I've been looking at some peoples' programs around here and I notice that a lot of them aren't using some neat tricks that may or may not make coding easier/neater.
Strings
The first thing is that a lot of people use double quotes instead of single quotes, but I think that's just a preference in most cases. In case you still aren't aware:
string1 = '' string2 = ""
Both of these string variables are valid. I should probably mention that you should be careful with using single quotes, because there are common words with apostrophes such as "don't" and "you're". To prevent errors, you should put backslashes before single quotes inside single quotes:
string1 = 'don't'
An alternate solution is to use double quotes in this case.
There's also this neat trick that I didn't learn until a little further down the line in my use of lua - multiline strings. Defined by [[ ]], much like ' ' and " ".
The following example is valid:
print [[This is a multiline string.]]
Be wary that using multiline strings with tabs before text will actually output the tabs as well.
print [[This string will take the tabbing with it.]]
Multiline strings are useful in printing menus for your console. Instead of doing this:
print '------------------------------' print 'Screen Title' print '------------------------------' print 'Option' print 'Option' print 'Option'
you can do:
print [[ ------------------------------ Screen Title ------------------------------ Option Option Option ]]
A similar helpful trick to multiline strings can be done with comments, starting with --[[ and ending with ]]:
--[[ This is a multiline comment. It does nothing :P/>/> ]]
I learned this very recently from an amazing youtuber named NitroFingers. You can use the # operator on strings to get the length of a string, much like string.len().
myString = 'waffles' print(string.len(myString)) --> 7 print(#myString) --> 7
I haven't tested this with all string methods, but in most cases, you'll usually be able to perform the method on the actual string instead of calling the method with the string as an argument.
local s = 'waffles' s:sub(1,3) --> waf s:match 'f.-s' --> fles for i,v in s:gmatch '.' do print(v) end --> w --> a --> f --> f --> l --> e --> s
Functions
Function calls are also flexible in other ways. In the case that a function only takes one argument and it is a string, you don't have to supply parentheses.
print('a string') print 'a string'Both of these examples will print a string.
Unless you're getting deep into some OOP stuff, this won't be very helpful to you in a lot of cases. If a function takes a table argument, you can drop the parentheses, like strings.
myFunction { a = 1; b = 2; }
There's also an alternate way of defining functions.
myFunct = function() -- stuff end
For me, this is useful for defining functions without having to go outside your table:
myTable = { funct1 = function() print 'stuff' end; funct2 = function() print 'more stuff' end; } myTable.funct1() myTable.funct2()
Functions are able to be defined with a variable number of arguments:
function stuff(...) end
The three dots represent the table of arguments given and can me accessed in the function as "arg".
function stuff(...) for i,v in pairs(arg) do write(v) end end stuff(1,2,3,'a','b','c') --> 123abc6
Woah wait, where'd that 6 come from? That's just the number of arguments given. It's indexed in the "arg" table as n.
print(arg.n) --> 6
However you'll still get the number of arguments given if you use the pound sign operator, as it only counts values given as indexes.
print(#arg) --> 6
At the end of the day, it's all a matter of preference. To make things less complicated, you can simply store your arguments in a local table, as shown by some computercraft base programs.
tArgs = { ... }
Tables
When defining indexes in tables, you can actually use semicolons instead of commas. For me, this is easier because I can rearrange elements of the table without having to redo my commas.
myTable = { index1 = "foobar"; index2 = 1337; }
In case you didn't know this either, you can also use strings to access indexes not defined by strings. This would be helpful for storing functions for possible user input in tables.
local answers = { yes = 'You're cool!'; no = 'Fine, be that way.'; } print 'Do you like pineapples?' input = read() -- this is accepted as a string. if answers[input] ~= nil then print(answers[input]) else print 'I don't understand you, sorry.' end
Numbers
There isn't much to learn in this category, however I think you'll eventually find it useful that you're actually able to concatenate numbers like strings.
print(3 .. 3) --> 33There need to be spaces in between the dots and the numbers, otherwise lua will confuse your dots as decimals and throw an error.
Some of you coming from a different programming background may have already known this, but the function math.fmod() can be replaced with the operator %. If you don't know what this does, it returns the remainder of the division of two numbers. e.g. 7 % 3 would equal 1.
You could use this to tell if a number is even - if the remainder of the number and 2 is 0.
while true do textutils.slowPrint 'Type in a number.' write '> ' local input = read() local num = tonumber(input) if num then --checking if the input was successfully converted into a number if num % 2 == 0 then textutils.slowPrint 'Your number is even.' else textutils.slowPrint 'Your number is odd.' end elseif input == 'exit' then --give the ability to leave the program. textutils.slowPrint 'Thank you for using my useless program! :D/>/>' sleep(1) break else textutils.slowPrint "That's not a valid number!" end sleep(1) end
Booleans
In the bools field, there's actually a cute little statement that is way easier than if ... elseif ... end:
var = condition and set_if_true or set_if_falseFive unnecessary lines condensed into one. Here's an example:
var = 5 > 3 and 'yes!' or 'aw'In this case, var would be 'yes!' because 5 > 3. If on some distant alien planet in a parallel universe 5 were less than three, var would be 'aw'.
If you wanted to have a bit of fun, you can make yourself a clamp function by nesting these.
local function clamp(low,n,high) return n < low and low or (n > high and high or n) end
There's also a simple way of reversing a boolean:
bool = not bool
In a more applicable example, you could make a sort of toggling light switch program with one line (assuming your output is in the back and hooked up to your lights)
rs.setOutput('back', not rs.getOutput('back'))
Oh, and remember that % example? This:
if num % 2 == 0 then textutils.slowPrint 'Your number is even.' else textutils.slowPrint 'Your number is odd.' end
Could be this:
textutils.slowPrint('Your number is ' .. (num % 2 == 0 and 'even.' or 'odd.'))Brackets needed because it isn't just one string anymore XD
You could've lived your life without knowing any of this, really. However I thought it'd be helpful to some of you people, a couple of interesting tidbits to know. Pretty sure I'm missing some stuff but I'm not necessarily a book of infinite useless lua knowledge />
#24
Posted 11 September 2012 - 10:30 PM
#25
Posted 11 September 2012 - 11:45 PM
#26
Posted 13 September 2012 - 03:12 PM
#27
Posted 16 September 2012 - 05:42 AM
The pairs function lets you loop over all the things in a table. For example:
local meanings = { python = 'a British comedy show', lua = 'the moon', java = 'a type of coffee', haskell = 'a famous computer scientist', c = 'the third letter of the alphabet', } for key, value in pairs(meanings) do print('The language ' .. key .. ' is named after ' .. value) end
But if you're going over a sequence (i.e. where the keys are numbers), pairs won't guarantee you'll get the values in order. Also, as you've shown with your vararg example, it often ends up returning extra values such as the length of the sequence.
To solve that issue, Lua has an alternative function called ipairs:
local languages = { 'python', 'lua', 'java', 'haskell', 'c' } for index, value in ipairs(languages) do print('At index ' .. index .. ' we have ' .. value) end
#28
Posted 17 September 2012 - 11:54 PM
I might include it in the future.
#29
Posted 18 September 2012 - 06:53 AM
for i = 1, #tableTest do print("k: ", i, " v: ", tableTest[i]) end
#30
Posted 19 September 2012 - 03:22 AM
for i=1, #aTable do print(i, aTable[i]) --longer end for i,v in pairs(aTable) do print(i, v) --shorter end
Even though in this example it's just one statement, coding would be faster and easier in the longrun using "v" instead of "aTable[i]".
#31
Posted 24 October 2012 - 03:26 AM
#32
Posted 24 October 2012 - 06:39 AM
({1,2,3,4,5})[2]==2
this seems pretty useless but it can be used to get a specific parameter from a function. for example if you only want the message from rednet but not the id we typically use
local _,message=rednet.receive()
but we could also use
local message=({rednet.receive()})[2]
#33
Posted 24 October 2012 - 08:02 AM
KaoS, on 24 October 2012 - 06:39 AM, said:
({1,2,3,4,5})[2]==2
this seems pretty useless but it can be used to get a specific parameter from a function. for example if you only want the message from rednet but not the id we typically use
local _,message=rednet.receive()
but we could also use
local message=({rednet.receive()})[2]
I usually use select to do that
local message = select(2, rednet.receive())
#34
Posted 24 October 2012 - 08:37 AM
#35
Posted 24 October 2012 - 10:48 AM
KaoS, on 24 October 2012 - 06:39 AM, said:
({1,2,3,4,5})[2]==2
this seems pretty useless but it can be used to get a specific parameter from a function. for example if you only want the message from rednet but not the id we typically use
local _,message=rednet.receive()
but we could also use
local message=({rednet.receive()})[2]
I could tell people about the option to throw your function calls into a table and get specific arguments out of them, too. I myself don't prefer to do this but some would definitely benefit from knowing it.
#37
Posted 28 October 2012 - 02:03 AM
So
"Hello World!" Is fine in most languages but 'Hello World!' can cause issues in some.
#38
Posted 28 October 2012 - 06:30 AM
bbqroast, on 28 October 2012 - 02:03 AM, said:
So
"Hello World!" Is fine in most languages but 'Hello World!' can cause issues in some.
The only difference between double and single quotes is that double quotes can have single quotes inside, and vice versa.
"It's useful if you want to have a statement with an apostrophe,"
'or if you want to "emphasize" something within single quotes.'
#39
Posted 30 October 2012 - 08:59 PM
Kingdaro, on 28 October 2012 - 06:30 AM, said:
bbqroast, on 28 October 2012 - 02:03 AM, said:
So
"Hello World!" Is fine in most languages but 'Hello World!' can cause issues in some.
The only difference between double and single quotes is that double quotes can have single quotes inside, and vice versa.
"It's useful if you want to have a statement with an apostrophe,"
'or if you want to "emphasize" something within single quotes.'
Also if you're doing a tutorial you need to remember that the reader may wish to move onto languages (LUA is a nice starting language) and it's bad to teach them thigns that will come back to bite them later.
#40
Posted 31 October 2012 - 08:35 AM
1 user(s) are reading this topic
0 members, 1 guests, 0 anonymous users