#Closures in Crafting Interpreters

1 messages · Page 1 of 1 (latest)

upbeat ether
#

I’ve hit something of a roadblock in my Lox implementation when it comes to closures. Every implementation I’ve glanced at uses some kind of mutable object for the closure environment (which is stored alongside the Function declaration) that can be shared and gets cleaned up by the GC when all references to it are out of scope in the host language. (NOTE: the way environments are implemented so far is kind of in a linked list manner, whenever we enter a new block/function/etc a new environment is created and the current one is set as the 'enclosing' environment)

I had a solution in mind but it feels kind of bad:

Have some sort of map in the root (global) environment (or in some actor) that maps References to Environments, and give the Function declaration a Reference to some closure. When evaluating a call you just get the closure from the root. Then, whenever we're done evaluating the call, check the entire Enviroment (including all enclosing envs until the root) if there are any References in any Function somewhere on there and delete the closure entry if not.

To be fair I'm not even sure if the above works, I haven't really tried it, but I was wondering how you guys would tackle / have tackled something like this. Sorry if it's unclear, I can make my repo public if need be.

(For reference: https://craftinginterpreters.com/functions.html#local-functions-and-closures)

#

The problem currently when following the book is that eg with this snippet the second invocation of counter() doesn't have the mutations to the closure that the first applied:

fun makeCounter() {
  var i = 0;
  fun count() {
    i = i + 1;
    print i;
  }

  return count;
}

var counter = makeCounter();
counter();
counter();
dusty saffron
#

The book avoids implementing GC and mutation by using the host language GC and mutation

#

If you want to implement it in a language without those you will need to implement it

#

The easy solution is to use an ETS table and to never clean it up until the program finishes running

upbeat ether
#

Guess I'll have to learn how to implement GC 👍

dusty saffron
#

I think the second half of the book will cover that

#

The C version

upbeat ether
#

Oh k interesting hmm

dusty saffron
#

Go for the no-GC ETS approach for now

upbeat ether
#

Aight thanks!

upbeat ether
#

it's not pretty but it works 🤝