More ipairs Confusion

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
RileySunshine
Prole
Posts: 7
Joined: Tue Jun 14, 2016 3:05 pm
Location: Wonderland

More ipairs Confusion

Post by RileySunshine »

I ran into another development problem that Im having a hard time wrapping my head around.

I was working on a couple functions to create an ingame sign with some text on it.
I have seen a couple of differrent ways to do it, but Im mostly wondering why what I have written doesnt work.

I think the problem is in love.load(), specifically in the ipairs part.(Line 31 - 41)
It seems to not be setting the text to the right values, also won't override previous values.
The first line of text should say "This is line 1 of the Sign," and not "Line 1." ("Line 1" is my placeholder)
Ive had a couple problem with colored text tables, but this has me completely confused.

I've included a .love file for others to audit, your expert opinion is appreciated.
With Löve,
Riley S.

PS: It's probably something obvious, I have problems spotting obvious errors.
Attachments
SignTest.love
(40.37 KiB) Downloaded 112 times
Begin again, let go.
Janzo
Prole
Posts: 8
Joined: Sun Jul 31, 2016 1:20 am

Re: More ipairs Confusion

Post by Janzo »

Your problem is in love.draw(). You're drawing the wrong table, the one that says, "Line 1", which is textLine.one. You really should be printing the table signText.line1.text.

The love.draw you have, incorrect:

Code: Select all

if signBool then
		lg.draw(sign.img, sign.x, sign.y)
		lg.print(textLine.one.text, textLine.one.x, textLine.one.y)
		lg.print(textLine.two.text, textLine.two.x, textLine.two.y)
		lg.print(textLine.three.text, textLine.three.x, textLine.three.y)
	end
The fixed love.draw that prints what you want:

Code: Select all

if signBool then
		lg.draw(sign.img, sign.x, sign.y)
		lg.print(signText.line1.text, textLine.one.x, textLine.one.y)
		lg.print(signText.line2.text, textLine.two.x, textLine.two.y)
		lg.print(signText.line3.text, textLine.three.x, textLine.three.y)
	end
Here's a .love file with your code fixed that it prints "This is line 1" instead of "Line 1".
Attachments
SignTest.love
(39.81 KiB) Downloaded 125 times
I'M SORRY, BUT DOES REALLY BOLD TEXT BOTHER YOU
RileySunshine
Prole
Posts: 7
Joined: Tue Jun 14, 2016 3:05 pm
Location: Wonderland

Re: More ipairs Confusion

Post by RileySunshine »

Hello Janzo,
Thanks for trying to help me out with this problem, unfortunately this solution will not work with what I am going for.
I should probably have mentioned in my post that signText variables are static and will never change.
On the other hand, textLine variables are not static. textLine.lineX.text needs to be able to be switched out with other signText(s).

Example:
There are 4 lines of text, of which 3 can be displayed. When the user presses enter, all text gets shifted up by one spot.
Meaning, the first line of text disapears, all other texts are shifted up by one, and the 4th line is added.

However, I'm not looking for how to do this. I only am wondering why textLine.XXX.text seems to reject any attempt at setting its values through ipairs.

I have uploaded all larger portion of the code if that helps.

Thanks,
Riley S.
Attachments
SignTestLarge.love
(42.11 KiB) Downloaded 115 times
Begin again, let go.
User avatar
zorg
Party member
Posts: 3444
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: More ipairs Confusion

Post by zorg »

I found your problem. You haven't read "Programming in lua" or "Pil". :3 But i'll be nice and explain in detail.

In your code, you define textline as such:

Code: Select all

textLine = {one, two, three}
Now, this does absolutely nothing apart from create an empty table, and assign it to the variable textLine.

After, you create three string keys in the table, "one", "two" and "three", then later, you try, with ipairs, to iterate over the numeric indices of the textLine table... that don't exist.
(Technically, keys and indices are the same in this context, they are used the same, it's just good to treat them separately, depending on whether you're using a table as a numeric sequence or a list/dictionary/whatever.)

Also, your code kinda confuses the two tables you're using; you're actually trying to use textLine[l].tag, which doesn't even exist, only with signText... except you can't, because those are inside the five sub-tables called line1 to line5, which you didn't want to use in the first place?
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
RileySunshine
Prole
Posts: 7
Joined: Tue Jun 14, 2016 3:05 pm
Location: Wonderland

Re: More ipairs Confusion

Post by RileySunshine »

Heya Zorg,
Sorry for my confusing code, your response has me confused as well.

"Also, your code kinda confuses the two tables you're using; you're actually trying to use textLine[l].tag, which doesn't even exist,"
You are correct, textLine[1].tag does not exist, and it was never supposed to. (textLine should never have a tag value)
Only signText[1].tag exists, and it refuses to be compared using ipairs.

Here is the long and short of it: I hate the implementation of colored text, it drives me nuts.

I tried having a table that was like this:
black = {0, 0, 0, 255}
text1 = {black, "This is Text!", tag = 1}

Because I added tag to the end of the table, it now refuses to be defined as a colored text object.
So instead i tried to have a table for the "colored text object" and it's tag the other table is basically a placeholder for the "colored text object" as well as it's x and y positions.

"because those are inside the five sub-tables called line1 to line5, which you didn't want to use in the first place?"
I actually very much wish to use those values, i just can't seem to call them out of the table.

Thanks,
Riley S.

Edit: Clarity
Edit 2: Added small attachment, If you can tell me whats wrong with this tiny attachment, I wont have to use any of the confusing code.
Attachments
TinyProblem.love
(1.15 KiB) Downloaded 102 times
Begin again, let go.
palmettos
Prole
Posts: 14
Joined: Sun May 29, 2016 7:00 pm

Re: More ipairs Confusion

Post by palmettos »

On line 5 in main.lua you're creating empty keys in textBox. This will fix the problem:

Code: Select all

textBox = {text=text, tag} -- note tag is still nil
Read this. ;)
User avatar
zorg
Party member
Posts: 3444
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: More ipairs Confusion

Post by zorg »

Code: Select all

local highlight = "lua highlight pls..."
function HighLight(language) return "I SAID lua", ":(" end
-- Ignore the above lines...

a = {x}           -- return a[x] -> nil; return a.x -> nil; return a[1] -> nil
b = {"x"}         -- return b[x] -> nil; return b.x -> nil; return b[1] -> "x"
c = {x = "."}     -- return c[x] -> nil; return c.x -> "."; return c[1] -> nil
d = {[x] = "."}   -- return d[x] -> ***; return d.x -> ***; return d[1] -> ***
e = {["x"] = "."} -- return e[x] -> nil; return e.x -> "."; return e[1] -> nil

-- ***: x is a variable in the d case, so the following will work if and only if the variable is defined

local x = "x"
d = {[x] = "."} -- d[x] is set to ".", x == "x" so d["x"] is "."
return d.x -- also works, since for string keys, t.s is the same as t["s"].
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
User avatar
4aiman
Party member
Posts: 262
Joined: Sat Jan 16, 2016 10:30 am

Re: More ipairs Confusion

Post by 4aiman »

RileySunshine, you really have to consider delving into PiL at some point :)
Zorg's example is a great one. Just read that very carefully.

1. ipairs
What Zorg tried to convey is that ANY table has TWO parts: indexed one (numeric keys) and hashed one (with anything used as a key).
Now, when you write

Code: Select all

mytable = {one, two, three}
you create a "numeric" table with 3 elements all of which is nil.
But when you create a table like this

Code: Select all

mytable={one="first item", two={"some item", 42}, ['REALLY UNNECESSARY CAPS HERE']="super glue is the culpit!!!111one"}
you make a "hashed" table.

Now, ipairs CAN'T traverse the hash part of a table. And when all your fields are hashed... Right, you're going to get nothing from ipairs.

To get those elements inside "hashed" part of a table, you should use pairs (w/o "i", just pairs)

Code: Select all

for k,v in pairs(mytable) do ...
Until you'll learn the difference, use "pairs".


2. Now to your sample

Code: Select all

red = {255, 0, 0, 255}
text = {red, "Help"}
textBox = {text, tag}
You've creates a table "text" with 2 fields. Indexed, numerical fields.
text[1] is equal to the value stored inside the "red" variable.
text[2] is equal to "Help"

You could've write that like this:

Code: Select all

text={}
text[1]=red
text[2]="Help"
Now, textBox contains 2 elements. AGAIN, those are in the numeric-indexed part of a table.

Code: Select all

textBox[1]=text
textBox[2]=tag -- the "tag" variable is nil, so textBox[2] is going to be nil to
Ergo, textBox does NOT contain the "text" field.
It only contains the "text" table you've declared just prior to declaring the textBox variable.

By printing

Code: Select all

lg.print(textBox.text, 160, 160)
you're doing a wrong thing, as if you wanted to output a red text which says "Help", you should've done this:

Code: Select all

lg.setColor(textBox[1][1]) lg.print(textBox[1][2], 160, 160)
Now if you want to type textBox.text then you should declare thing like this:

Code: Select all

red = {255, 0, 0, 255}
linedef = {color=red, line="Help"}
textBox = {text=linedef}
Then and only then you'll be good to do this:

Code: Select all

lg.setColor(textBox.text.color) lg.print(textBox.text.line, 160, 160)
User avatar
zorg
Party member
Posts: 3444
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: More ipairs Confusion

Post by zorg »

Actually, i wanted to edit my previous post so it's a bit more clear, but this way is fine too. :3

I'd mention that pairs is, for a few reasons, actually "worse" of an iterator than ipairs:
- pairs goes in an arbitrary order, and every time you use the iterator even on the same table, the order may be completely different.
- in a "bigger" project, pairs will be very slow, slower than ipairs.
Depending on your use-case, it may be acceptable, of course.

As for a clearer, hopefully complete example of how one can create (and index) tables, i give you a bit more cleaned up code example; this one you can actually run in the online lua testbed.

Code: Select all

-- Assign the string "j" to the (local) variable i.
local i = "j"



--[[ Very compact ]]--

-- first numerically indexed field of t = the variable i
-- full form: t[1] = i
t = {i}
print(t.i, t[i], t["i"], t[1])

-- first numerically indexed field of t = the string "i"
-- full form: t[1] = "i"
t = {"i"}
print(t.i, t[i], t["i"], t[1])

-- syntax error, you need to assign something to a key
--t = {[i]}



--[[ Compact ]]--

-- the field of the tabe t indexed by the string "i" = the variable i
-- full form: t["i"] = i
t = {i = i}
print(t.i, t[i], t["i"], t[1])

-- the field of the tabe t indexed by the string "i" = the string "i"
-- full form: t["i"] = "i"
t = {i = "i"}
print(t.i, t[i], t["i"], t[1])

-- syntax error, "i" is not a key.
-- t = {"i" = i}

-- syntax error, "i" is still not a key.
-- t = {"i" = "i"}



--[[ Full forms ]]--

-- t[the variable i] = the variable i, errors if the variable i is nil, can't have nil keys.
t = {[i] = i}
print(t.i, t[i], t["i"], t[1])

-- t[the variable i] = the string "i", errors if the variable i is nil, can't have nil keys.
t = {[i] = "i"}
print(t.i, t[i], t["i"], t[1])

-- t[the string "i"] = the variable i
t = {["i"] = i}
print(t.i, t[i], t["i"], t[1])

-- t[the string "i"] = the string "i"
t = {["i"] = "i"}
print(t.i, t[i], t["i"], t[1])
As for accessing table members/fields, the dot syntax is equivalent to the []-syntax when whatever inside the bracket is a string.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
RileySunshine
Prole
Posts: 7
Joined: Tue Jun 14, 2016 3:05 pm
Location: Wonderland

Re: More ipairs Confusion

Post by RileySunshine »

Dear Zorg & 4aiman,
Thank you both so much for your help, really appreciate it. To be fair, I have read PiL a bit.(Haven't read all of it, tables section still confuses me)

To 4aimain:
Thank you so much for your help yet again, you always are able to phrase things in a way that are easy to understand.
What I got out of your reply the most was this line:

"Now, ipairs CAN'T traverse the hash part of a table. And when all your fields are hashed... Right, you're going to get nothing from ipairs."

That helped me understand exactly why this was failing, plus now I know what the "i" in ipairs stands for.
During my short time developing love games, I have always used table.insert to add things to tables, and then ipairs to "use" them.
I see now that table.insert is adding indexed values/tables, whereas I was adding non-indexed values/tables.'
Once again thanks, that one line helped everything click together in my mind.

To Zorg:
Thanks for taking time out of your day to help me understand this.
I had a hard time understanding your second reply, but your third reply is filled with very interesting information.
Lots of good nuggets of information in there, thanks.

I really appreciate the explanation of why pairs may be a worse choice in certain situations, little things like that are hard to pick up from tutorials and refrence documents.
As far as use cases, this section of code will exclusively used to write a few lines of text on a screen. Seeing as it wont happen very often, and wont be called upon often either, I think it may be the proper use case for this.
Seriously though, thanks for that tip. I'll keep your advice on ipairs vs pairs handy, I seem to be using ipairs a lot lately.

To Both:
Once again thanks for the help, I would've been working that out for a long time if you guys had not helped.


With Löve,
Riley S.
Begin again, let go.
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 59 guests