Log In  


what the heck is going on?

s={1,2,3} print(s[2]) s[1]=nil s[5]=999 print(s[2])
2


This looks like another fixed-point indexing bug.

Internally in Lua, the addition of s[5] causes 2 and 3 to be re-indexed because the keys are no longer continuous from 1, and end up with key values shifted right 16 bits (0x0.0002, 0x0.0003) because of the hack-job I did to get fixed point work in 5.2. I'm not sure yet why this doesn't happen in the second example.

The only workaround until I fix this is just to avoid using nil values in a sequentially indexed array :(


Maybe more test cases will help get this fixed:

> a={} a[1]=1 a[2]=nil a[3]=3 print(a[3])
3
> a={} a[1]=1 a[2]=nil a[3]=3 a[4]=nil print(a[3])
3
> a={} a[1]=1 a[2]=nil a[3]=3 a[4]=nil a[5]=nil print(a[3]) 
nil
> a={} a[1]=1 a[2]=nil a[3]=3 a[4]=4 a[5]=nil print(a[3])
3
> a={} a[1]=1 a[2]=nil a[3]=3 a[4]=nil a[5]=5 print(a[3])
nil

I burned yet another day isolating this. Between this and the last bug I isolated (the "-1"+0 problem), maybe you should warn us how absurdly broken the interpreter is before asking us to commit our money and time (especially the time) to this platform that now annoys the heck out of me (mostly due to these interpreter bugs). This bug is just about a project killer -- I haven't decided yet -- too frustrated at the moment to want to spend time hacking in the workarounds. I'm quickly running out of tokens and it will steal a lot of tokens to work around not relying on the nil value in a data-heavy game.


Now that I've gotten over the trauma of eliminating all the red herrings to find this bug, I've realized that "false" is a workable replacement for "nil" in my code -- even though it abuses the data types, which grates me the wrong way. I will still take some small token penalty for this where I rely on the packing behavior of nils, but at least I don't have rewrite all the conditions to comparisons to some out-of-range value.


@juanitogan

...maybe you should warn us how absurdly broken the interpreter is before asking us to commit our money and time (especially the time) to this platform that now annoys the heck out of me (mostly due to these interpreter bugs).

In zep's defense, PICO-8 is still in alpha, and zep hasn't really claimed it's a finished product (yet).
Do please give him some time, and some slack. :)


I wish I had heard about the fixed point indexing bugs earlier.

My game started behaving strange a while back. It took a long time until I started doubting the sanity of the table implementation.

In the end the "solution" is that I call this lovely function after every time I modify a table with integer only keys:

function repair(d)
 local fixed={}
 for k,v in pairs(d) do
  --printh(k..": "..list2str(v).."->"..shl(k,16))
  if k<1 then
   d[k]=nil
   fixed[shl(k,16)]=v
  end
 end
 for k,v in pairs(fixed) do
  d[k]=v
 end
end

Since I got bitten by this particular bug I would put it extremely high on the TODO list for pico-8. And before it is fixed it should be listed as a known bug in the manual.


@Offler: nice workaround! you can shrink it a little:

function repair(d)
  for k,v in pairs(d) do
    if (k<1) then d[shl(k,16)]=v d[k]=nil end
  end
end

(for some reason setting d[k]=nil first triggers a runtime error, maybe something you stumbled on?)

it's been more than a year since that was reported, so yes, should have been a big caveat in the manual.


@ultrabrite, thanks for the improvement! I was almost ready to ragequit pico-8 and never return when I wrote it, so I took the safe route. I just felt that I didn't want to alter the table I was looping through.


@JeremyRedhead, I hear ya and I agree somewhat... but whether you call something alpha (which is not stated as such on the main page -- only implied by the version number) or whatever -- what you call it is pretty irrelevant once you start charging for using it. Once you start doing that then typical expectations of quality, support response, and maintenance timelines need to be met. Otherwise, you lose the trust of your customers. Considering the age of this bug and other bugs, and lack of effort in at least maintaining a known issues document, it appears to me that PICO-8 has been abandoned and left in a state not worth charging for.


@Offler, Yeah, after losing personal lifepoints over this (as well as unreliable integer conversions from strings), I totally see why you went the safe route. These are both such low-level and severe bugs, if I were responsible for publishing them I would be greatly embarrassed and would have hotfixed them immediately. Given that, I have little faith left that these things will be fixed.


Considering the age of this bug and other bugs, and lack of effort in at least maintaining a known issues document, it appears to me that PICO-8 has been abandoned and left in a state not worth charging for.

Other than, you know, that bit where it is still being actively developed, improved and released.

I for one am entirely happy with how the PICO-8 is progressing and I am glad I paid to use it. I don't know zep, so i can't make excuses, but working on a project on your own is never easy, and your attitude isn't helpful.

EDIT: I've never encountered situations where this kind of bug would affect me, and I imagine not many people do, so i wouldn't even come close to ranking this bug with the sort of severity you are attributing to it. It doesn't stop people making fun projects, and (hopefully) no one is being harmed financially for trying to create their projects in the PICO. No sane person pins their income on a platform which is obviously advertised as alpha and incomplete.


I think this is the shortest piece of code that demonstrates the problem:

t={1,2}
t[1]=NIL
t[3]=3

?t[2] -- Prints NIL 
?t[0x.0002] -- Prints 2

I'm still happy with my purchase of pico-8, but I will not recommend it to anyone until this bug has been fixed. Tables are so central to LUA that they just have to function correctly.


@springogeek - I can see this being a potential problem for 'sparse' hashtable-like structures whose entries change from valid to nil values regularly (e.g. grid-based collision detection + moving objects).

I have a vested interest in that working properly, so poked around with this a bit. It seems that as long as the table isn't resized* after manually deleting a previously valid value, things will stay put. So by reversing the order of t[1]=nil & t[3]=3 in Offler's last post things work out:

-- Offler's test case, reversed
t={1,2}
t[3]=0
t[1]=nil -- not really needed, see next line

-- original test, after fix
t[1]=nil
t[3]=3

print("#t = "..#t)
for i=1,3 do
print("t["..i.."]="..(t[i] or "nil"))
end

However, it does mess with the array length calculation in certain cases:

-- in this version, a different index is deleted - #t is now junk but the data can still be indexed correctly
t={1,2}
t[3]=3
t[2]=nil

print("#t = "..#t) -- ruh roh
for i=1,3 do
print("t["..i.."]="..(t[i] or "nil"))
end

This 'fixes' the original test case as well (which involves sparse entries).

So, if you don't mind not relying on the # operator to read table sizes, an alternative workaround is:

  • declare your table as normal
  • add a dummy entry at the maximum index you intend to use (+1 to prevent it being nil'ed out later?).
  • nil & update things to your heart's content.
t={1,2,...,n}
t[max]=0xDEAD.BEEF -- max > n

You can still run into the bug if you change indices above or including the dummy entry, but it can at least now be rationalized away as a buffer overflow coming from your own code.

*=Disclaimer: it's possible doing this is not actually triggering an initial resize/reserving the range of keys, or whatever it's doing under the hood, so this needs more testing before using it for any non-toy code or larger table sizes. edit: checked it up to 20 elements (fits on pico-8's screen. I also checked 2000, but far less thoroughly) with various inputs - seems ok so far. Using t[0] is also ok.


@springogeek, I find it inappropriate when those who haven't been through the valley of death start judging the attitudes of those who have. And this is my second trip through it with PICO-8. In both cases, it appears to me that zep couldn't care less about fixing the issues any time soon, if ever. Thus, to me, it is zep's attitude that isn't helpful, if anybody's.

PICO-8, in it's current state of non-support, is a lemon, and this is disappointing considering the potential it seemed to have. Would I have bought the product and invested time with it if I expected to be disappointed by it? I will likely finish the project I have been working on but, at this point, it will be in spite of zep and not in support of zep. Try getting your heart broken like that heavily into a project and then see how your attitude is.

Catatafish demonstrates the real damage of low-level issues like this, regardless of the frequency of them. Trust. It is difficult to want to use something where low-level functions cannot be trusted. Even if you can identify and workaround the extent of the issues, there still remains little trust that something else related won't also break or change the issue behaviors in the next update. Thus, when something breaks with a future update, where do you look? Your code? Your workarounds? The updated tool? What, then, is the expected fix turnaround if the PICO-8 is broken? 1 year? 2 years? A bleak future to set yourself up for when you, yourself, expect to have your own set of users to support in turn.

I don't know how you build stuff but I care about all issues at all stages of development and production. I find any lesser attitude unhelpful. If zep would respond, great. But zep's not... not this issue nor other issues. And, let's face it, once you start charging for a tool, it's in production -- even if you still call it alpha. You can't even try it before you buy it. What does that say?

Finally, thanks for implying that I'm insane or that I may be pinning too many expectations on PICO-8 when you have no idea what I'm working on or why. Very helpful attitude there in progressing the conversation. Check your own before you check mine. Just because someone has a different view than you doesn't mean that something is wrong with their attitude. My goal is to generate enough interest to get this fixed -- otherwise I wouldn't be spending time on this board. Your goal appears to be to kill my goal. That confuses me.


Would love to visit the valley of death! Is that the one across from the gulch of overstatement? Next to the harbor of hyperbole?

I work a lot with tables in Pico-8 and have never encountered this bug—possibly because I'm allergic to using "nil" as a type.* But if you must use it for now, couldn't you work around this problem by defining a new object called "null" and using that instead of nil everywhere in your code? e.g.

null={}

s={1,2,3} 
print(s[2]) 
s[1]=null 
s[5]=999 
print(s[2])

Aside from that, I think the bug has been sufficiently reported, yes? (Calling Pico-8 a lemon seems a bit excessive given the number of cool new projects that continue to pop up on this forum...)

*The inventor of the null reference called it "a billion-dollar mistake"—for good reason, I think.


It's amazing the flack you get when you criticize people's favorite stuff -- regardless of intent to help.

I've been around a while and, as a result, this is the engineering culture I live in:

A bug report is more helpful than no report.

A repeatable bug report is more helpful than a non-repeatable report.

More intel is more helpful than less intel.

Expression of frustration over features, bugs, or how to do things differently is more helpful than no feedback -- even though it may hurt a bit because some people go overboard in their expressions of frustration and/or they touch on things we otherwise like. We can either take it personally, or take it as a call to action to build a better product.

Obviously, however, such values are not welcome here by some people. Instead, I can only suppose some think we should wish for things to magically work themselves out because PICO-8 is too cool to be judged against typical standards. Maybe, just maybe, I have some right to be somewhat concerned that this table bug was reported over a year ago, and that another unfixed PICO-8 bug that also betrays sloppy engineering was reported last July -- and both with a lack of concern behind them by the maker.

@mursurca, Thank you for the suggested workaround. Such things have already been mentioned. The problem with that workaround, as mentioned, is the impact on tokens. The test of "if a==null" takes more tokens than "if a" (according to what I read about tokens). It adds up. The workarounds, however, are beside the deeper points of quality and trust.

If this has been sufficiently reported, it would have been fixed a long time ago [in a galaxy far, far away].

On a side note, be careful how you talk about nulls. There is a difference between null pointers and null (unknown) values. Getting hung up on what Tony Hoare said about his regret for null references as a slander also against null values is a good way to get fired in my field. I've seen someone fail to get their contract renewed because of failure to understand the differences between unknown data, no data, 0, "", etc., because of getting hung up on this topic. I don't want to make this a discussion about the usefulness of nil values in data tables, just be careful of how you speak about your allergy to nil if you want to gain respect. Better you hear that now from someone you have chosen to mock than learn it the hard way.


Fixed for 0.1.11


Any idea when 0.1.11 will be released?



[Please log in to post a comment]