ID:139056
 
Code:
client
proc/SetDblClickCommandObjsFromAtom(var/atom/thisAtom)

var/list/verbListToPass = thisAtom.GetPlayerCommandVerbs()

#warn For some reason verbListToPath cannot inherit the contents...

if (isnull(verbListToPass)) CRASH ("[type].SetDblClickCommandObjsFromAtom() cannot fetch verb list.")
SetCommandObjectListFromVerbList(verbListToPass)

atom
proc/GetPlayerCommandVerbs(var/list/inheritedPlayerCommandVerbs)

var/list/playerCommandVerbs

if (inheritedPlayerCommandVerbs == null) playerCommandVerbs = new/list()
else playerCommandVerbs = inheritedPlayerCommandVerbs.Copy()

for (var/thisVerb in playerCommandVerbs)
if (thisVerb == null)
DebugMsg("atom.GetPlayerCommandVerbs, null verb removed.")
playerCommandVerbs.Remove(thisVerb)

if (playerCommandVerbs == null || playerCommandVerbs.len == 0)
return(null)
else
DebugMsg("[type].GetPlayerCommandVerbs() returning [playerCommandVerbs.len] length list.")
return(playerCommandVerbs)


Problem description:
For some reason, I can't seem to pass this list. The above CRASH is triggered with this error:

runtime error: /client.SetDblClickCommandObjsFromAtom() cannot fetch verb list.
proc name: SetDblClickCommandObjsFromAtom (/client/proc/SetDblClickCommandObjsFromAtom)
source file: PlayerCommand.dm,117
usr: Geldonyetich (/mob/player)
src: Geldonyetich (/client)
call stack:
Geldonyetich (/client): SetDblClickCommandObjsFromAtom(Nanite cannon (/obj/device/nanitesystem/cannon))
Geldonyetich (/client): SelectNewAtomToCommand(Nanite cannon (/obj/device/nanitesystem/cannon))
Geldonyetich (/mob/player): SelectNewAtomToCommand(Nanite cannon (/obj/device/nanitesystem/cannon))
Nanite cannon (/obj/device/nanitesystem/cannon): Click(Alchelite wall (81,85,2) (/turf/personal/wall/alchelite), "paneView.mapDefault", "icon-x=30;icon-y=21;left=1;scr...")
/obj/device/nanitesystem/cannon.GetPlayerCommandVerbs() returning 6 length list.


Note the "/mob/creature/human.GetPlayerCommandVerbs() returning 6 length list" message at the end coming from my DebugMsg() proc. We know there's definitely a 6-length list there immediately before it is returned() but it never gets there!

I can't help but think this is something really obvious, but I can't figure out what.

I originally simply simply stuck thisAtom.GetPlayerCommandVerbs()inside of the arg for SetCommandObjectListFromVerbList() but I was getting null on the other end.
Not even a guess, huh?

I'm going to say it's probably one of these two things:

1) The list is falling out of scope and being consumed by the garbage collector.

2) There's a stack limit to keep that list in scope, and I passed it.

Found a workaround, but that didn't do me any particular good seeing how I apparently can't do verb arithmetic with text2path anyway.
I think I figured it out. This is a simple problem with wrapping my head around passing lists that I seem to have trouble with.

This does not work:
var/list/cosmos/myContentsList = GetListOfContents()

By the very next line, myContentsList is null.

However, this will work:
var/list/cosmos/myContentsList = new()
for (var/cosmos/thisThing in GetListOfContents())
myContentsList.Add(thisThing)

Or a compacted version of the same:
var/list/cosmos/myContentsList = new(GetListOfContents())


What I was expecting would happen is that, because GetListOfContents() has already allocated the memory to the list with new() before returning that list, all I need to do is have some variable pointing to it for that list to stay in scope.

This is not the case. The list is garbage collected the instant the line containing the call to the proc is done. I have to reallocate memory again, in order to store the list, before it falls out of scope by the next line.

The reason why this is tough for me to grok is because no other type of variable works this way.

If I were to do this, for example:
var/thisNumber = GetThatNumber()

That would work just fine because it's just a simple assignment of data to a variable.

So also would this:
var/myDatum/thisDatumReference = GetThatDatum()
Because all datums need is a reference to stay in scope.

It's a bit of a double standard that /list does not behave in the way any other variable does when it comes to practical scope life. That's why I had to relearn this lesson all over again after taking a few months off from coding.
I don't see anything obvious. /lists are objects, and should only be garbage collected when their reference-count reaches zero. You might have stumbled onto a rare bug.
Can you show us where you override that process?
In response to Geldonyetich
I've created a test library to try to reproduce it but am unable to. I'm not sure exactly what's going on here.
In response to DarkProtest
I'd like to show you the whole command stack but, even though I keep incremental backups between milestones, I'm afraid the particular code that lead to this bug was smack dab in the middle of two milestones, the latter leading to the complete removal of the whole command object idea. I attempted to recover it, but was unable to do so.