Trying to understand Lua simple codes - lua

I'm having some trouble with Lua. The thing is: there are some Lua codes I know what they do but I didn't understood them, so if the professors ask me to explain them, I wouldn't be able to do it.
Can you help me with this?
I know this code separates the integer part from the decimal part of a number, but I didn't understand the "(%d*)(%.?.*)$" part.
int, dec = string.match(tostring(value), "(%d*)(%.?.*)$")
This code insert on a table all the data from a text file, which is written following this model entry {name = "John", age = 20, sex = "Male"). What I didn't understand is how do I know what parameters the function load needs? And the last parameter entry = entry, I don't know if I got exactly its meaning: I think it gets the text_from_file as a piece of Lua code and everything that is after entry is sent to the function entry, which inserts it on a table, is it right?
function entry(entrydata)
table.insert(data, entrydata)
end
thunk = load(text_from_file, nil, nil, {entry = entry})
thunk()
That's it. Please, if it's possible, help me understand these 2 pieces of Lua code, I need to present the whole program working and if a professor ask me about the code, I want to be sure about everything.

For the first question, you need to learn a little about lua patterns and string.match.
The pattern (%d*)(%.?.*)$ is comprised of two smaller ones. %d* and %.?.*. The $ at the end merely indicates that the matching is to be done till the end of string tostring(value). The %d* will match 0 or more numerical values and store the result (if found, otherwise nil) t the variable int.
%.? matches a literal . character. The ? means that the . may or may not be present. The .* matches everything and stores them into dec variable.
Similarly, for the second code segment, please go through the load() reference. You have the following text in your file:
entry {name = "John", age = 20, sex = "Male")
It is equivalent to executing a function named entry with the parameter (notice that I used parameter and not parameters) a table, as follows:
entry( {name = "John", age = 20, sex = "Male") )
The last parameter to load defines the environment for the loaded string. By passing {entry = entry}, you're defining an environment in which you have a function named entry. To understand it better, look at the changes in the following segment:
function myOwnFunctionName(entrydata)
table.insert(data, entrydata)
end
thunk = load(text_from_file, nil, nil, {entry = myOwnFunctionName})
Now, the custom environment passed to load will have a variable named entry which is actually the function myOwnFunctionName.

Related

Lua How to create a table inside a function?

I'm a beginner at Lua and programming in general (I've had some experience in other languages but nothing huge) and I've been following a tutorial where there's this one exercise on tables:
"Make a function with a table in it, where each key in the table is an animal name. Give each key a value equal to the sound the animal makes and return the animal sound. Try invoking the function and see if you get back the correct sound."
Here's my current solution:
make_sound = function(input)
animal_sounds = {
["cat"] = "meow",
["dog"] = "woof"
}
return animal_sounds.input
end
print(make_sound("cat"))
This just prints 'nil'. I've tried so many variations of this but they all either print 'nil' as well or give me an error saying something about nil (sorry I can't remember the original message or erroneous code).
I know this is a really dumb question and probably has an extremely basic answer so I'm sorry for my stupidity. All the other exercises have been a breeze and then I suddenly get hit with this thing for an hour. I searched everywhere but could only find results about functions inside arrays or something else completely. I didn't want to just give up on a seemingly easy task so here I am...
If your function returns the whole animal_sounds table, though it is not what is asked of you, you get the animal sound by print(make_sound().cat):
make_sound is a function,
make_sound() returns a table,
make_sound()['cat'] is a field of that table,
and make_sound().cat is syntactic sugar for it, as is said in the answer above.
Also, better declare everything local, including function make_sound and animal_sounds table.
And you can skip [""]/[''] in table keys, if they are strings of basic Latin, numbers and underscores: cat = 'mew' not ['cat'] = 'mew'.
Unless you are going to use make_sound as a variable, it is better to declare it with local function syntax, rather than an assignment.
You can skip parentheses around the only string or table parametre in the function call: f'str' rather than f( 'str' ).
Most imporantly, your function never uses input, which is supposed to be the animal. Therefore, it has to return not the table, but the sound. So, move the [] part inside the function.
So:
local function make_sound( input )
local animal_sounds = {
cat = 'meow',
dog = 'woof',
cow = 'moo'
}
return animal_sounds[input]
end
print( make_sound 'cat' )
P.S. You can even make the table anonymous, though it will need to be surrounded with parentheses, otherwise Lua will think that return is not the last operator before end as it should be:
local function make_sound( input )
return ({
cat = 'meow',
dog = 'woof',
cow = 'moo'
})[input]
end
print( make_sound 'cat' )
Try this:
return animal_sounds[input]
The animal_sounds.input is equivalent to animal_sounds["input"] and your table does not have the "input" key, hence it returns nil.

lua table index is null error

I am trying to write a lua switch, based on what I have read so far it seems this is achieved by using a table. So I made a really barebones table but when I try to run it I get an error saying table index is null.
Ultimately what I want is based on different input, this code should call on different lua files. But for now since I am new to this language I figured I would settle for not having that index error.
thanks
#!/usr/bin/lua
-- hello world lua program
print ("Hello World!")
io.write('Hello, where would you like to go?\n')
s = io.read()
io.write('you want to go to ',s,'\n')
--here if i input a i get error
location = {
[a] = '1',
[b] = '2',
[c] = '3',
[d] = '4',
}
location[s]()
Above is the code that I got so far. Below is the error.
~$ lua lua_hello.lua
Hello World!
Hello, where would you like to go?
a
you want to go to a
lua: lua_hello.lua:11: table index is nil
stack traceback:
lua_hello.lua:11: in main chunk
[C]: in ?
The table code is based on this example here: Lua Tables Tutorial section:Tables as arrays
What appears to be the issue is that location[a] is setting location at index a, which is not a string. When you enter a into your input, it gets read as 'a' which IS a string. Index [a] is different from index ['a']. What you want is to replace your assignments so that they're assigned to strings (location['a'] = '1').
As Ihf has said, if you want to print the output then you need to call print(location[s]) because location[s] will simply return the string '1' (or whichever value, just as a string). If you want to assign the numeric value (to use for calculations or etc) then you should use location['a'] = 1.
Alternatively, keep the value as-is as a string and when you attempt to use the value, simply use tonumber().
Example: x = 5 * tonumber(location[s]).
I hope this was helpful, have a great week!
Try
location = {
['a'] = '1',
['b'] = '2',
['c'] = '3',
['d'] = '4',
}
Then that error goes away but is replaced by attempt to call a string value (field '?') because location['a'] is the string '1'.
Perhaps you want
print(location[s])

How to define variable that named by function?

I need to create many variables, and I want to do declare these variable's name by function. In like this:
function DefineVariable(VariableName)
return VariableName = 123 end
What i want from the function is:
DefineVariable(weg423)
-- Result: weg423 = 123
But it was not easy as I thought... That function does not worked. I want to know how to turn it into working function.
And, could i receive an answer about this too?
a = "blahblah"
...somehow...
DefineVarByValue(a)
-- Result: blahblah = 123
Ah and one more question. how to change 'table variable' to 'string or number variable'? (i mean the 'number expected, got table' error...)
All simple types in Lua are passed by value, so your DefineVariable function gets the current value of the variable weg423 and not the name of it, which means you can't change the value of weg423 from the function.
If this is a global variable, then you can pass the name of that variable (for example, DefineVariable('weg423')) and the function can then change the value of that variable by referencing it as a key in _G or _ENV table (_G[VariableName] = whatever).
I still don't see a point in doing it this way. There is nothing wrong with using weg423 = 123.

Elder Scroll Online Addon

This is my first time working with Lua, but not with programming. I have experience in Java, Action Script, and HTML. I am trying to create an addon for Elder Scroll Online. I managed to find the ESO API at the following link:
http://wiki.esoui.com/API#Player_Escorting
I am trying to make a function that returns a count of how many items each guild member has deposited in the bank. The code I have so far is as follows
function members()
for i=0, GetNumGuildEvents(3, GUILD_EVENT_BANKITEM_ADDED)
do
GetGuildEventInfo(3, GUILD_EVENT_BANKITEM_ADDED, i)
end
I am having trouble referencing the character making the specific deposit. Once I am able to do that I foresee making a linked list storing character names and an integer/double counter for the number of items deposited. If anyone has an idea of how to reference the character for a given deposit it would be much appreciated.
I don't have the game to test and the API documentation is sparse, so what follows are educated guesses/tips/hints (I know Lua well and programmed WoW for years).
Lua supports multiple assignment and functions can return multiple values:
function foo()
return 1, "two", print
end
local a, b, c = foo()
c(a,b) -- output: 1, "two"
GetGuildEventInfo says it returns the following:
eventType, secsSinceEvent, param1, param2, param3, param4, param5
Given that this function applies to multiple guild event types, I would expect param1 through param5 are specific to the particular event you're querying. Just print them out and see what you get. If you have a print function available that works something like Lua's standard print function (i.e. accepts multiple arguments and prints them all), you can simple write:
print(GetGuildEventInfo(3,GUILD_EVENT_BANKITEM_ADDED,i))
To print all its return values.
If you don't have a print, you should write one. I see the function LogChatText which looks suspiciously like something that would write text to your chat window. If so, you can write a Lua-esque print function like this:
function print(...)
LogChatText(table.concat({...}, ' '))
end
If you find from your experimentation that, say, param1 is the name of the player making the deposit, you can write:
local eventType, secsSinceEvent, playerName = GetGuildEventInfo(3,GUILD_EVENT_BANKITEM_ADDED, i)
I foresee making a linked list storing character names and an integer/double counter for the number of items deposited.
You wouldn't want to do that with a linked list (not in Lua, Java nor ActionScript). Lua is practically built on hashtables (aka 'tables'), which in Lua are very powerful and generalized, capable of using any type as either key or value.
local playerEvents = {} -- this creates a table
playerEvents["The Dude"] = 0 -- this associates the string "The Dude" with the value 0
print(playerEvents["The Dude"]) -- retrieve the value associated with the string "The Dude"
playerEvents["The Dude"] = playerEvents["The Dude"] + 1 -- this adds 1 to whatever was previous associated with The Dude
If you index a table with a key which hasn't been written to, you'll get back nil. You can use this to determine if you've created an entry for a player yet.
We're going to pretend that param1 contains the player name. Fix this when you find out where it's actually located:
local itemsAdded = {}
function members()
for i=0, GetNumGuildEvents(3, GUILD_EVENT_BANKITEM_ADDED ) do
local eventType, secsSinceEvent, playerName = GetGuildEventInfo(3, GUILD_EVENT_BANKITEM_ADDED, i)
itemsAdded[playerName] = (itemsAdded[playerName] or 0) + 1
end
end
itemsAdded now contains the number of items added by each player. To print them out:
for name, count in pairs(itemsAdded) do
print(string.format("Player %s has added %d items to the bank.", name, count))
end

How to fix "attempt to concatenate table and string"?

I asked a question similar to this the other day, but another bug popped up "attempt to concatenate table and string"
local questions={
EN={
Q2={"Who is the lead developer of Transformice?","Tigrounette"},
Q4={"What is Eminem's most viewed song on youtube?","I love the way you lie"},
Q6={"What is the cubic root of 27?","3"},
Q8={"What are the first 3 digits of Pi","3.141"},
Q10={"What is the most populated country?","China"},
Q12={"What is the plural of the word 'Person'?","People"},
Q14={"Entomology is the science that studies ...?","Insects"},
Q16={"Who was the creator of the (bot ran) minigame fight?","Cptp"},
Q18={"The ozone layer restricts ... radiation","Ultraviolet"},
Q20={"Filaria is caused by ...","Mosquitos"}
}
local main = questions.EN["Q"..math.random(1,20)].."%s" -- bug here
local current_answer_en = string.gsub(current_question_en,1,2)
What type of object is questions.EN["Q"..math.random(1,20)]? Say random is 15, what type of object is questions.EN["Q6"]? It is a {"What is the cubic root of 27?","3"}, which is a table, which Lua doesn't know how to concatenate with a string ("%s" in your case). If you want to concatenate with the first item of this table, then
local main = questions.EN["Q"..math.random(1,20)][1] .. "%s"
Note however that you will need the "random with step" function that I posted in math.random function with step option?, otherwise you could get that the table EN["Q"..something] is nil (if the random number is an odd number, in the code you posted).
Note sure what you are trying to do with current_question_en but if you are trying to extract the question and answer you could do something like this:
local QA = questions.EN["Q"..math.random(1,20)] -- this is a table
local question, answer = QA[1], QA[2]
The other option is that you build your table like this:
local questions={
EN={
Q2={q="Who is ..?", a="Tigrounette"},
Q4={q="What is ...?", a="I love the way you lie"},
...
}
}
Then you could use
local QA = questions.EN["Q"..math.random(1,20)] -- this is a table
print("The question:", QA.q)
print("The answer:", QA.a)
Not sure what you're trying to do with string.gsub but it does not take integers as 2nd and 3rd args.

Resources