ID:1998787
 
(See the best response by Lummox JR.)
Code:
var/list/entries = list() //Our list holding lists in our table. Holds our columns.
...
New(columns)
world.log << "Creating [columns] columns..."
columns = text2num(columns) //make sure this is a number
if (columns == null)
columns=0

for (var/a = 1,a <= columns, a++)
var/list/col = list() //An empty list (our "column") should be initialized.
entries += col //Place it into our columns list
world.log << "[entries.len]" //returns 0? Seems that empty lists are not even created/are just chucked out?

...
//Something's broken. var/list/col = list() should be a list, not set itself as a value.


Problem description:

I was creating my own implementation of a resizable table, because, well, as far as I know arrays aren't resizable (ex. array[num] = new) but lists() are. But after toying around and noticing some odd proc crashes, of particular they are mainly saying that the indices were out of bounds. That shouldn't be right, as there should be empty lists...

I then decide to initialize each list (col) with a null entry, and there were, as expected, three columns(and of course plenty of proc crashes ripe for debugging).

I then tried to initialize with "test" (var/list/col = list("test"); should have had one entry) and I got THIS error:

runtime error: Cannot read "test".len
proc name: AddRow (/Table/proc/AddRow)
source file: Tables.dm,54
usr: null
src: /Table (/Table)
call stack:
/Table (/Table): AddRow(1)
/SpawnManager (/SpawnManager): BuildSpawnList("\n1 13\n1 13\n1 13\n1 14\n1 14...")
/Database/RoomBuilder (/Database/RoomBuilder): Build()
world: BuildDatabases()
world: Setup()
world: New()
runtime error: Cannot read "test".len


However, initializing with var/list/col = list(list()) places a list there.

Which pretty much means that instead of a list, I get a value instead. Does anyone else get this?
DM doesn't have arrays, all it has are lists. Thus, a resizable table will just be a list of lists. A simple implementation would be something like,
table
var
colsize
rowsize

// In doing something like src.data[a][b], a will be the
// row and b the column, matching with standard matrix
// notation.
list/data = new

New(_rowsize, _colsize)
src.SetSize(_rowsize, _colsize)

proc
At(i, j)
return src.data[i][j]

Set(i, j, _data)
src.data[i][j] = _data
return src.data[i][j]

SetSize(_rowsize, _colsize)
src.rowsize = _rowsize
src.colsize = _colsize

src.data.len = src.rowsize
for(var/i = 1, i <= src.rowsize, i ++)
var/list/col = new
col.len = src.colsize

src.data[i] = col


[Edit]

And as for your error, looking over it real quick I don't see the problem. You'd have to show your AddRow() method to work it out.
Best response
The problem is you're adding a list to a list. When you do A += B and both A and B are lists (this is the same for the Add proc), B's contents are appended to A, rather than B itself. Because B is empty, it has no contents and therefore nothing is appended to A.

The correct way to build a list of lists one at a time would be to add something else, like null, and then set that list element to another list.

        for(var/a = 1, a <= columns, a++)
entries += null
entries[i] = list()
In response to Lummox JR
Oh! I forgot about that wacky little nuance. Thanks a bunch!
Also, thanks a bunch, Popisfizzy, for that bit of info there.

Lummox JR wrote:
The problem is you're adding a list to a list. When you do A += B and both A and B are lists (this is the same for the Add proc), B's contents are appended to A, rather than B itself. Because B is empty, it has no contents and therefore nothing is appended to A.

The correct way to build a list of lists one at a time would be to add something else, like null, and then set that list element to another list.

        for(var/a = 1, a <= columns, a++)
> entries += null
> entries[i] = list()


An alternate way, which will be better on memory, but possibly worse on performance depending on your plans for the class, is a single list. It would be something like,
table
var
rowsize
colsize

list/data = new

New(_rowsize, _colsize)
src.SetSize(_rowsize, _colsize)

proc
At(i, j)
return src.data[src.colsize*(i-1) + j]

Set(i, j, _data)
var/pos = src.colsize*(i-1) + j
src.data[pos] = _data
return src.data[pos]

SetSize(_rowsize, _colsize)
src.rowsize = _rowsize
src.colsize = _colsize

src.data.len = src.rowsize * src.colsize


The tradeoff here is that the first implementation will use r*c+1 list objects, so if you have 50 rows and 50 columsn, there would be 2,501 list objects. This implementation will only ever use one. The performance hit would be if you're doing a lot of processing on individual columns, though honestly it should be an extremely minimal hit. I think lists are implemented with a self-balancing BST, and lookup is usually log(n) for them.