Log In  

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:

P#77176 2020-05-25 16:54

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.

P#77177 2020-05-25 17:14 ( Edited 2020-05-25 17:14)

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.

P#77178 2020-05-25 17:23

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?
P#77179 2020-05-25 17:53 ( Edited 2020-05-25 17:54)

@shy

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.

P#77183 2020-05-25 18:46 ( Edited 2020-05-25 18:46)

@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. :)

P#77186 2020-05-25 19:31

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-03-19 03:29:04 | 0.024s | Q:14