I'm sure this is probably an easy answer, but why do these work differently, where co_anim1 resets to nil after completion, but co_anim2 does not?
function _init() co_anim1=cocreate(animate) co_anim2=cocreate(animate) end function _draw() cls() --first method if (co_anim1 and costatus(co_anim1)!="dead") then coresume(co_anim1) else co_anim1=nil end --second method, same as first, --but sent to a function to do --the work. resume(co_anim2) print("co_anim1:",0,0,5) print(co_anim1,36,0,7) if (co_anim1) print(costatus(co_anim1),75,0,7) print("co_anim2:",0,6,5) print(co_anim2,36,6,7) if (co_anim1) print(costatus(co_anim1),75,6,7) end function resume(co) if (co and costatus(co)!="dead") then coresume(co) else co=nil end end function animate() local a=rnd() for i=1,40 do circ(64+cos(a)*i,64+sin(a)*i,4,7) yield() end end |
This code results in this behavior:




The variable co passed into your resume function is local to the function, so setting it to nil doesn't affect co_anim2 at all. Both coroutines finish normally, the second one just isn't getting nil'd out.



Thank you! I got the same answer in the PICO-8 Discord. I was thrown because because if you pass a table by reference, and change the values in the table, it of course changes the original table, since it's passed by reference. But it didn't occur to me that setting the local variable to nil wouldn't set the reference to nil, but would instead just re-point the local variable itself away from the reference and to nil.



Yeah, that's definitely a quirk of pass by reference that takes some getting used to. Since I didn't mention this last time, if you want to have this function work, you could put "return co" at the end of it, and then do this elsewhere:
co_anim2 = resume(co_anim2) |
You could optimize tokens further by using the true/false return value of coresume to do something inline like this, but it's probably less clear this way:
co_anim2 = coresume(co_anim2) and co_anim2 or nil --untested, but you may not even need the "or nil" part? |



If you want co_anim2 to go specificially to nil, then yes, you need the "or nil" part. Otherwise it'll go to false.
If you just want to be able to say if co_anim2 (or maybe if not co_anim2) then you could omit the "or nil" part.



@Felice: Yeah, that's what I figured for the assignment. But there's some weirdness I'm doing here for token optimization, like potentially calling coresume(nil) or coresume(false) on the next iteration, if I omit that "if" test entirely. I'm also not sure if calling coresume() on a dead coroutine to get the first false/error is efficient enough, so I'd want to test all of that out. I just wanted to vaguely warn MBoffin about all of that -- this shorthand could work, but it's probably not the best way to go if you want code clarity. :)
[Please log in to post a comment]