This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
HaddockDev's profile picture

How can you switch between ipairs and pairs?

Started by HaddockDev, 12 November 2017 - 12:48 PM
HaddockDev #1
Posted 12 November 2017 - 01:48 PM
I have a GUI API that allows me to create, well, GUIs. Problem is that I need to switch between ipairs and pairs in order for clicking to work.

Here's where clicking is handled (in a for loop), and sorry for my cruddy coding and OOP.

...
for k,v in ipairs(self.Scene.View) do
...

Thanks in advance.
KingofGamesYami #2
Posted 12 November 2017 - 02:03 PM
What? Why would you need to do that? I suppose you could write your own pairs-ish function, but I seriously doubt it's worth the effort.
HaddockDev #3
Posted 12 November 2017 - 02:32 PM
What? Why would you need to do that?
I have a program that tests the various functions of my API, and when I have 2 buttons, I can click neither of them unless I'm using pairs.
I suppose you could write your own pairs-ish function, but I seriously doubt it's worth the effort.
I probably could, but most likely not.
SquidDev #4
Posted 12 November 2017 - 02:34 PM
I have a program that tests the various functions of my API, and when I have 2 buttons, I can click neither of them unless I'm using pairs.
Why not just use pairs then? If that works, is there any reason to use ipairs? I'm afraid I'm a little confused about the question, as it's not entirely clear what your problem is or what you're trying to achieve - a little more code and context would be useful.
HaddockDev #5
Posted 12 November 2017 - 03:06 PM
-snip
Why not just use pairs then? If that works, is there any reason to use ipairs? I'm afraid I'm a little confused about the question, as it's not entirely clear what your problem is or what you're trying to achieve - a little more code and context would be useful.
I can't just use pairs. If I throw another button into the mix, I need to use ipairs.
Basically, I have 2 buttons. They both work perfectly fine using pairs. Can't use ipairs though. (probably because of the way i'm storing them: id, then OOP class)
If I throw another button into the mix, making it 3 buttons, I can use ipairs, but not pairs. If I use pairs, then nothing works.

Here's a little more code, this is from the API

elseif e[1] == "mouse_click" then
            --find what it clicked on
            local x = e[3]
            local y = e[4]
            local button = e[2]
            for id,t in pairs(self.Scene.View) do
                if t.X <= x and t.Width + t.X >= x then --x matches
                    if t.Y <= y and (t.Height or 1) + t.Y >= y then --y matches, this is the right object
                        if t["OnClick"] ~= nil and type(t["OnClick"]) == "function" then
                            t:OnClick(x,y,button)
                        end
                        break
                    end
                end
            end
I look through all the objects in the scene using pairs, see if the X and Y matches up (and they do, but not in ipairs with 2 or pairs with 3), then call the OnClick function.
It works with pairs using this code:

local me = QuickDraw.Init() --initing stuff
QuickDraw.AddObject(button) --defined earlier
me.Scene.BG = colors.black
me.Scene:Add("button", "b1")
me.Scene:Add("button", "b2")
--defining properties and stuff
…but if I through in another button, (me.Scene:Add("button","b3")), then pairs doesn't work and I have to switch to ipairs.

That's the best that I can explain it, anyway.
my internet sucks at the moment too, so its hard to post things and it takes a long time for it to go through
Exerro #6
Posted 12 November 2017 - 03:25 PM
What's the form of `self.Scene.View`? If it's a list with indexes (1..n) then there's no reason `ipairs` shouldn't work. Otherwise, you'll have to use pairs.

If you do use pairs, it should work as long as you don't have any overlapping elements. The only reason it wouldn't is that `pairs` doesn't really respect any sort of order, so maybe you've got a background element without a click function that's eating up the event and doing nothing about it.
HaddockDev #7
Posted 12 November 2017 - 03:38 PM
What's the form of `self.Scene.View`? If it's a list with indexes (1..n) then there's no reason `ipairs` shouldn't work. Otherwise, you'll have to use pairs.

It is a table holding objects. Keys are IDs, values are OOP classes/tables.

Anyways, I think I've fixed it. It was more of an error on my part, but I think the problem was the names on the for loop and (i)pairs, maybe even my misunderstanding of this stuff. after further testing, it was. also, i didn't edit because of my internet being bad n stuff.
But, thanks anyways.
Exerro #8
Posted 12 November 2017 - 03:47 PM
`ipairs` iterates through the indexes (1..#t), `pairs` through all indexes in the table, but in no defined order.
Luca_S #9
Posted 12 November 2017 - 04:36 PM
`ipairs` iterates through the indexes (1..#t), `pairs` through all indexes in the table, but in no defined order.

This also means that ipairs might skip certain entries in some cases, e.g.:

local a = {
  [1]="Hello ",
  [3]="World"
}
or

local a = {}
a.test = "Hi"