Lua Notes

All Files in aoc/2015/1/
Login

Files in directory aoc/2015/1 in any check-in


AOC 2015 day 1

'Unecessary Coroutines' edition

I treated the coroutines here as similar to processes in Erlang (or actors in an actor framework, generally): communicating exclusively with messages, and maintaining internal state. This adds a lot of visual and computational overhead, compared to simply solving the problem as in n3.nelua.

So this certainly isn't a good case for coroutines. It does, however, show that you can treat coroutines like Erlang processes and do message-passing if you like, and what the result could look like. The message-passing somewhat resembles use of typed channels in golang, using a statically-typed discriminated union to send different messages as variants of a single type, rather than using pattern-patching and dynamic types. The messages in this case are also value types that could simply be copied if passed to a coroutine running in another thread, similar to Erlang's copy-everything approach.

But, this also doesn't really exploit coroutines as they are. Coroutines are not Erlang processes. The concurrency here also does not involved threads, but cooperative multitasking in the same thread, sharing the same memory. Even if you wanted to hold the door open to spawning 10k concurrent Santas for a race, shared memory could be used instead of message passing - this is what n5.nelua does.

Some points:

  1. coroutine.pop() is safe to use on an empty stack, and returns false in that case.
  2. coroutine.resume() is also safe to run against a dead coroutine, and returns false in this case.
  3. ... also, .resume() can take arguments. I didn't notice this until n6.nelua. There's no need to .push and then .resume
  4. the long basement.arg.basement.reached names, but not the nested constructors, could be flattened - see flattened discriminated unions
  5. coroutine.yield() can fail if the caller lets the stack fill up, which resulted in pretty mysterious infinite loops since I wasn't checking it
  6. pushing/popping multiple arguments seems like a relative hassle to keep correct (see previous point)
  7. if you push N arguments and then pop 1 argument, you're popping the Nth argument rather than the 1st argument that was pushed. Hence, n6.nelua puts the code as the last argument pushed to santa