Log In  


Now that I'm mixing and matching my metaphors in programming, metaphorically speaking of course, I'm running into some curious behavior by Pico-8.

For instance, take this code:

a="1"
b=2
?a+b

Which gives you 3, and that's fine.

But if you do this:

a="1"
b={1}
?b[a]

The result is NIL. Now I already know why it is because it's a string, but wouldn't it be easier for Pico (and possibly other programmers) to remove the number "type" completely and instead treat all variables as strings, only doing calculations when desired, and even then the results while visually appearing numerically are still just in truth a string ?

We already have ".." to show linking two strings together so there would be no difficulty with getting the "+" chosen correctly for calculations in determining whether or not it needs to be added to or appended to.

What problems would typecasting everything as a string cause ?

I can already see one advantage. Since strings can be any size this could also mean Pico-8 could be upgraded by @zep and allow numbers with any number of digits in them, both to the left and right of the decimal place. It would break the -32767.9999 and 32767.9999 barrier.



There are plenty of good reasons for why not to do this. Performance would suffer immensely, as strings would have to be converted to a proper binary representation for each operation. Determining which representation, if any, is appropriate would require looking through the entire string. Memory size would increase, as a number in Pico-8 takes up 4 bytes. I don't know if Pico-8 has a special character representation, but normally each character is at least a byte and can't possibly be half of that. Implementing such a system would likely be pretty time consuming as well.

I would also normally argue that the error checking provided by types is incredibly valuable, but Lua already hardly does it.

If you want something beyond the standard number range, a better solution would be to use metatables.


I'm making the assumption that Pico is - ah... - how do I put this, in restraints, heavily. :)

I mean if I can set it aside for the moment and then bring up a game like Little Nightmares and play it which clearly has MILLIONS of polygons and instruction code that runs clear gigaflops on my computer - surely Pico-8 tiny little OS that it is can handle string-values only at zero lassitude to both the console and programmer, or at least make an option for it.

And this is not an unfamiliar thing with me. Prior to finding Pico-8 I was working on building a game programming language that had everything merged.

It was different from regular BASIC coding in that you could say A="Apple" and then pull out each character of it via [], its ascii via, {}, and if you tried to view it as an array, you would not get an error. It would say it was 5 elements in size and element would contain the ASCII value of each character.

You could say A=37 and it would be similar. [] would convert to chr() string if possible, {} would have no effect as it was already returning a numeric value, and if you tried to view it as an array, it would say that it is has one element and that first element would contain the value 37.

To force connecting strings you used ++ instead of +

This system I was working on could also deal with numbers of any size and any number of characters, well exceeding 2^32 and beyond. It worked everything as strings internally and you decided how many decimal places of accuracy you wanted in your code for calculations.

Yet I'm unfamiliar with that term you used, what are metatables, Shoxidizer ?


2

Metatables are a feature of Lua that allow tables to make use of the basic syntax. I hadn't used them before, and I'm still not too comfortable with them. Its also possible that Pico-8 has some special properties for them.

I think I got a basic demo working of how to use them for numbers with extra abilities. Attached is a cartridge that makes use of metatables to create a counter that exceeds the upper limit of the default numbers. It only supports addition and can only be a positive integer. It could be used as a score counter or timer. I even used a string to store the number, no need to overhaul the type system for that. Please look into the code to see how it is done. Implementing other operations shouldn't be too hard, at least for simple algorithms. Though I did have issue with the __tostring function.

I'm not sure there is anyway to index a table beyond the default number range though, that may be limited by how tables work anyways.

Cart #shox_string_count-0 | 2019-10-15 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
2


2

Metatables are mentioned in the pico-8 manual.

For a non pico-8 overview:

In the document Lua - an extensible extension language figure 9, under the heading "Fallbacks" might be of interest (particularly as I think @dw817 has been doing something similar but in a slightly different way recently). It starts around where the text goes "Many applications would benefit from an arithmetic expression parser ...". That document is dated 1996.

For a 2003 coverage of metatables, see chapter 13 of Programming in Lua

There are of course more recent documents regarding this.


Regarding fallbacks - before anyone asks what they are - these are the metamethods of metatables:

"These functions that customize certain Lua behaviour were called fallbacks in the first versions of Lua. In Lua 4.0 they were called tag methods. Now in Lua 5.0 (thanks largely to Edgar Toernig) these function are called metamethods and they are stored in tables called metatables." Source: lua-users.org


Before anyone asks - I was aware of metatables and had found the links above before now, but have not used them, so can't answer any questions about them that the links above don't anyway answer better.


THIS is why I am here ! :D To learn.

Wholly Smokes just how complex can you get ? It will truly take me a lifetime to learn what all Pico-8 has to offer let alone Metatables.

Thanks, Shoxidizer and remcode. It looks really powerful. Will spend the day exploring it, and your example code, Shoxidizer ...


Wanted to point out briefly, to those interested. Shoxidizer, you said you had difficulty confirming a variable to be a string ?

Well of course there is TOSTR() and TONUM() but a simpler way is:

number=value+0
string=value+""

It's that simple, and you'll see me making use of that in the recent book-reader I wrote as I was reading a string and wanting a numeric value out of it.

And that's all my brain can take for tonight ...


1

If I can take another crack at the explanation of metatables: Imagine storing a large integer as a simple Lua table with one decimal digit per entry: v = [1, 3, 5, 7, 9, 0, 2, 4]. An add(a, b) function could take two such tables and walk up the digits, carrying to the next place value as needed, producing a new table that represents the result: add([1, 3, 5], [2, 4, 6]) would return [3, 8, 1].

The "metatable" of an object describes how Lua's operators and syntax affect the object. You can modify the metatable of an object to change this behavior. So instead of an add(a, b) function, you can define the __add entry of a table-of-digits, then just use a + b to add, where a and b are both tables-of-digits. Shoxidizer's implementation above is storing the large numbers as strings instead of tables, but the idea is the same.

Yes, I think if you use strings in this way then you're limited to slicing substrings of strings as large as the largest integer value of the built-in number type (2^15 == 32,768). Storing decimal digits, your max value is 10^(2^15) (32,767 nines). You could expand to base 63 (all of PICO-8's string characters) and get 63^(2^15), which is a 58,961 digit decimal number.

If you use tables instead of strings, you could use non-numeric indexes into the table. You could even use the stringified bignum itself as the table key! :) Of course this would all be CPU and memory intensive.

You could do pretty well for efficiency if you use tables, store numbers in each cell, use all 32 bits of each number, then stick with 15-bit indexes (the built-in number type). That gives you a max value of (2^32)^(2^15), which is a 315,653 digit decimal number.

We get, what, two megs of Lua RAM? If we used all of it to represent a single integer, that's 2^16,777,216, which is a 5,050,445 digit decimal number.

Someone check my math, it's late. Or don't. =)


dw817, the issue I was having was with the __tostring function in the metatable. It is called when trying to convert the table to a string representation. If it worked, then using the table as a string would call that function, e.g. calling print() with the string-counter as the argument would print out the number. This would mean that you never have to refer to the internal structure of the string-counter.

dddaaannn, I don't know how lua implements its tables, espicially in Pico-8, but I would guess that using a counting string as the address would not work if you actually used all of its values. The tables are probably not big enough.

I'm not quite familiar with lua to know if it could be done, or how to do it, but if you wanted numbers bigger than tables while still having full precision, you could use a linked list of values.


1

You know ... I may be able to make a big number library in smaller code. Not that the library would be big, but the number. Add and subtract. Yeah, Wednesday is always a busy day but I think I have time to experiment.


https://www.lexaloffle.com/bbs/?tid=35680

Tried to make my own millions and billions of counter. And, it works great in Pico-8, but gets completely the wrong values in the BBS !

Augh, what gives ??



[Please log in to post a comment]