Log In  


Hello.

Could someone help me with this please ? I'm trying to understand how this works.

var={}
var["playhp"]=500
var["playname"]="patrick"
var["wepname"]="dagger"
var["wepstr"]=2

for i in all(var) do
  print(i.." "..var)
end

And yes, I know I can use:

var={["playhp"]=500,["playname"]="patrick",["wepname"]="dagger",["wepstr"]=2}

But I want to be able to iterate each item per line and in any order, and the ability to remove them as well.

var["playhp"]=nil

And to recall a value: print(var."playhp") returns 500. And ability to recall a value be reference:

varname="playhp"
print(var.@varname) also to return 500.

And print(#var) to return 4, currently returns 0 (zero).

Thanks in advance !



for key,value in pairs(var) do
  print(key.." "..value)
end

"#var" only works for contiguous integer-indexed tables
so I think you'll need to

count = 0
for key in pairs(var) do count++ end

oh, and also

varname="playhp"
print(var.playhp)
print(var[varname])

I was wondering about PAIRS() but couldn't find enough information for my exact example. Let me try what you did here.

Phew ! That got it. Let me try your counter.

Count++ is not recognized, shame, looks like an interesting shortcut, changed to count+=1 ... then it worked !

Experimenting on single variable view.
Ah ! This works. varname="playhp" print(var.varname)

Awesome, thank you so much, ultrabrite ! :D

This is all very new territory for me. both yield() and pairs().

Years ago I made a type of Virtual Variable Minder thing for S2 which allowed you 7-characters for variable name and 8-characters for the contents. Why 7 instead of 8 ? The 1st character was ">" and it was all neatly stored in a string that could go up to 32760-characters in size. You could use INSTR to search for ">" followed by the up-to-7-character name. At the time I thought it was a pretty good method, had a sort routine, import/export to file, etc.

exciting stuff ! Will try to put this new method above to good use.
Marking this part of the question complete.

Looks like I still have a few questions. See below.


Hmm ... These are the correct answers, it is odd that PAIRS() returns the items in any random order. Is there a way to return them sorted ?

It does actually say in the instructions,

"Order is not guaranteed."

How difficult can it be to display the paired items in the order in which they are received ?

And this doesn't work to display them sorted by virtual variable name, it may require PAIRS() since there are =2= values, a virtual variable and its contents.

for i,key in all(var) do
  print(var.i.." "..var.key)
end

Surely this can be improved upon.

var={}
var["playhp"]=500
var["playname"]="patrick"
var["wepname"]="dagger"
var["wepstr"]=2

sort1={} sort2={} sp=0
cls()
for k,v in pairs(var) do
  sort1[sp]=k sort2[sp]=v
  print(k.." "..v)
  sp+=1
end
repeat
  ok=1
  for i=0,sp-2 do
    if sort1[i]>sort1[i+1] then
      sort1[i],sort1[i+1]=sort1[i+1],sort1[i]
      sort2[i],sort2[i+1]=sort2[i+1],sort2[i]
      ok=0
    end
  end--next i
until ok==1
?""
for i=0,sp-1 do
  print(sort1[i].." "..sort2[i])
end

Lua tables have two parts: Sequence and non-sequence.

A sequence is represented under the hood as a simple array. The function all() (or ipairs() in standard Lua) iterates over the sequence, which are all the elements from index 1 and until the first nil. Order is guaranteed, since the indices are in order.

The non-sequence part of the table is represented as a dictionary, hash table, associative array or whatever your favorite programming language calls it. The function pairs() iterates over all index/element pairs in the table, whether they're part of the sequence or not. Order is not guaranteed, because the index can be anything and what it means to "order" those indices is not defined.

Standard Lua has table.sort for this, but in PICO-8 we need to implement it ourselves, as with so much else. Solutions have been discussed at length before: https://www.lexaloffle.com/bbs/?tid=2477


Hi Tobiasvl. Thanks for the reply.

While this is good information for a sort, I think what I'm looking for is a way to use "for var in all" with the data above:

var={}
var["playhp"]=500
var["playname"]="patrick"
var["wepname"]="dagger"
var["wepstr"]=2

Then it would be automatically sorted. At least I think so.


@dw817 I think what @tobiasvl is saying is that if you want what you're asking for, you have to implement it yourself and there's no real "right way" to do that, as per the linked discussion.


Well ratz. There are some good sort routines, better than what I wrote. Will go to look there, MBoffin.

Yet is there any technical reason why "Order is not guaranteed" ?

I mean I can understand them not being sorted but not to even be viewed in the order they are inserted and TRULY they appear to be in random order each time you run gets my head-a-scratchin'.

var={}
var["playhp"]=500
var["playname"]="patrick"
var["wepname"]="dagger"
var["wepstr"]=2

repeat
cls()
for k,v in pairs(var) do
  print(k.." "..v)
end
repeat
until btnp(4)
until forever

Press CTRL+R to see order rearrange each time.


Keeping a non-sequence ordered would still introduce an overhead though. The nice thing about a hash map is that insertion, removal and lookup are all really quick (they're O(1) in big-O notation), since all you need to do is compute the hash of the key to find the value.

To keep the insertion order, you need to sacrifice something. If you just keep the order value of each element, then deleting an element will take more time (O(N)) since you need to change the order for all subsequent elements. You can use a linked list, but that'll cost more memory. In both cases the extra information needs to be book-kept alongside the actual hash map, so you'd need to keep two data structures in sync at all times.

Hash maps/tables/dictionaries just don't bother with all that. The expectation is simply that they're kept efficient and sweet, not bothering with insertion order. No language I know of retain that information in their regular hash map data structures, although some offer one (like Python's OrderedDict). Lua, however, is a very simple language with a small core library.

If you make your own data structure that retains order (can probably be done pretty easily with metatables?) then be sure to report back how memory or CPU efficiency is affected!

So the reason it's not ordered is because that'd defeat the entire purpose of the non-sequence part of the table. If you want an ordered sequence of string/value pairs, then put those into a regular sequence as two-element tables, for example.

In Lua, the non-sequence part is often used as "object attributes" of a sort, so you write var.playhp or var.playname. In an object-oriented language, would you be surprised that an object's instance variables are not ordered?


var={}
var["playhp"]=500
var["playname"]="patrick"
var["wepname"]="dagger"
var["wepstr"]=2

Let me ask this then. Is it possible to use a FOR IN/DO statement with the data above ? Not using PAIRS() - and will list out the entries I made.

FOR i in all(var) do
  print(valu(i,key).." "..data(valu(i,key)))
END

. . .

As far as being surprised, yes, I would be. When I wrote S2 years ago I had in it a virtual-variable minder and it always kept the values alphabetical. You had an option to reverse it, or to sort by their keys also in forward or reverse order. Of course it really didn't reverse sort, it just output the results in reverse order so the user could debug something in that format if need be.


Without using pairs(), no, it's not possible with the data you've provided. You need to use pairs() (that's what it's for) or change your data structure.

If you write a valu() and data() function that does exactly that for you, then you've implemented what I mentioned in my last comment: A wrapper around a hash table that takes care of internal ordering, adding some overhead along the way.


Tobiasvl, what code that you could supply would be the best way to implement that ?

I mean I know I can do it with a fat string variable like S2 but there should be a simpler way for P8 to maintain natural actual order instead of artificially infusing it.


Wait ... I think I can do this sort of ...

-- virtual variable minder

function addvar(a,b)
local t={}
  t.valu=a
  t.data=b
  add(var,t)
end

cls()  
var={}

addvar("playhp",500)
addvar("playname","patrick")
addvar("wepname","dagger")
addvar("wepstr",2)

for i in all(var) do
  print(i.valu.." "..i.data)
end

That's a start, but then how would I access something like.

print(result(var,"playhp"))
result would be 500

WITHOUT going through every item in a FOR/DO loop.


What do you mean by "artificially infusing"? Doing it manually? You can use metatables to create a new kind of data structure. Here are some suggestions (vanilla Lua, but I'm pretty sure they should work in PICO-8 now that we have rawset()): http://lua-users.org/wiki/OrderedTable

In your example above you trade away lookup efficiency, which you probably don't want to do. You want to trade away deletion efficiency (ie. the only thing you give up, besides some memory to store the order, is the fact that you need to re-order elements when you remove them).


This is good reading ! I'll check here ...
Thanks, Tobiasvl.


Not to leave you hanging, tobiasvl, I think I'll stick with the PAIRS() method.

Artificially infusing to me is making something in code that appears to be simple work to the outside viewer but in fact is a pain to write for the actual programmer because of the language's limitations either believed or actual.

Artificially infuse in this case meaning for me - that I have to write my own sort routine to see a sorted PAIRS() list.

I only need the sort to appear visually, it does not make any difference their actual position later - so I can definitely chalk up a quick view the PAIRS by sort if need be.

Here's hoping future PICO gives us a robust INSTR(), RINSTR(), and REPLACE() later. I could work with these commands and always ensure my virtual variables are sorted alphabetically at all times and even from a single string. :)



[Please log in to post a comment]