Hi Pico 8 bbs!
I am following Lazy Devs' breakout tutorial, and I noticed he was using variables like so
ball_x=1 ball_y=1 |
In my code I had written:
ball={ x=1, y=1, } |
However I noticed that he had quite a bit fewer tokens than I did. I switched over, and sure enough, saved a bunch of tokens. This is because ball_x
is only one token, whereas ball["x"]
is quite a few more.
So then if straight-up variables are cheaper than tokens, it leads me to the question:
When is it actually a good idea to use tables instead of just variables?
Thanks!
Hello, for me I only use tables when the variables should be thought of as logically grouped together. For instance, to represent a player, I'd use table to hold position, speed, etc. In the code it's then easier to understand what the variables is as it is always referred to as player.x for instance, where player is the name of the table and x an element within the table.
Good question @tōbiō, @stirky for this example the variable might just be named player_x
which conveys just as much with fewer tokens. But one benefit of using a table I would point out is the ability to pass the entire table as an argument in a function call, e.g. hits(projectile, player)
which can be syntactically nicer and possibly save tokens in the long run.
Another benefit would be the dynamic nature of tables, for example enemies-as-tables can be added or removed from an any-sized "enemies list" table as needed, otherwise you will need to hard code all your enemies into the game. For projectiles this seems even more crucial (but I haven't quite gotten there in my own game yet)
I'm still learning PICO-8 so I might not be fully informed.
Both of the previous answers make good points. For breakout you're probably only going to have one ball so just having ball_x
and ball_y
is no big deal. But if you had 10 balls? Or 100? Global variables would be a terrible idea: you'd never be able to keep them all straight.
But grouping things together into logical groups—even if, strictly speaking, you don't need to—isn't necessarily a terrible idea either. Sure, your breakout game might only have one ball now but what if you want to add a power-up to have multiple balls later? How much code are you going to have to change to turn one set of global ball_x
, ball_y
variables into two or three or however many balls? That kind of thing is going to be much easier to add later if you already have a ball
data structure.
It seems to be conventional wisdom that tables are too expensive in terms of tokens and should be avoided as long as possible. I'm not convinced that's the case. I think it's just a matter of when in the process the extra tokens sneak in.
I don't have actual data to back this up so this is just opinion and you can decide for yourself what you think it's worth. But I think a table heavy approach has a higher initial cost early on in a project. So at the beginning of a project you can get things working quicker and with fewer tokens by avoiding tables. And since it's early in the project the difference in token cost is very noticeable.
But global variables are generally considered bad programming practice just about everywhere for a reason: they make code harder to reason about, more messy/spaghetti-fied, harder to debug, etc. Most importantly it can make code hard to change. When you can access something from anywhere you'll tend towards using it everywhere and if you change how it works, everything breaks.
So later in a project, when things are naturally getting more complex you'll discover problems with how you decided to do things early on which should really be changed but are going to be a huge pain in the butt to actually change. And so you'll write some kludgy code to make it work without having to change the early stuff. And then you'll do it again. And again until everything is basically just held together with metaphorical spit and duct tape.
What I'm getting at here is that while table heavy code has a higher initial token cost, global variable heavy code has a higher late stage token cost and the former is easier to observe/measure than the latter. My feeling is that, in the long run, the two approaches probably even out. But, again, I don' have actual data to back that up and reasonable people might disagree.
If variables actually are universally lower cost than tables I'd probably still write most of my code table-based until I started running up against the limits. Personally I'd rather have the flexibility for as long as possible and only start swapping stuff over to global variables to free up tokens when I had no other choice. But that's "personal preference" not "best practices."
Thanks for the well thought out answers!
Coming from FE dev, tables feel more natural for me, so I'll probably take @jasondelaat's advice and yeah, go with tables first until I run into issues.
I do wish dot notation was available haha
"I do wish dot notation was available"
It is. Both ball["x"]
and ball.x
will work and ball.x
is one less token.
Wow, I wonder why it wasn't working last time I tried. I'll give it another go.
I would not worry about variables vs tables too much in the beginning. programming is always about tradeoffs. tables help to modularise your code, which is helpful if the game grows and you have more and more code to dig through. Tables are LUA's Number 1 mechanism and are so engrained into the language that it's hard to totally work around them. Even if you are using only arrays you are using tables.
If you ever run into the token limit with one of your games you can think about these kind of optimisations.
Thats my take. But I am new to Pico as well and decided to not worry about this in the beginning.
[Please log in to post a comment]