First of all, I realize that this might go somewhat against the grain of Nim. And also it's not how I normally write code in Nim. I will start by explaining very briefly what I am doing and what's my motivation but feel free to skip to the last code example and the actual question following it. I'm currently experimenting with closures. I know that I can capture the reference to an object or an attributes of an object like so: type Book = ref object title: string var moby = Book(title: "Moby Dick") let getTitle = proc(): string = moby.title echo getTitle() Run
What I find interesting is that `getTitle` does not directly depend on the `Book` type. And also when I change the title of the book itself (i.e. `moby`) the `getTitle` function will return the correct (current) title. I can likewise implement a setter that can manipulate an attribute without an explicit reference to the type: let setTitle = proc(newTitle: string) = moby.title = newTitle Run Additionally, I can define these anonymous functions for (single, concrete) objects of different types (say `Movie` and `Book`) and then have a homogeneous access, meaning I can put multiple `getTitle` closures into a sequence `seq[proc(): string]`, even if they act on different types of objects. I'm currently using this approach in an experimental tweening library. I think tweening really is a cross-cutting concern and I want to keep the coupling to the objects being tweened very minimal. Sidenote: This looks somewhat similar to implementing `getTitle[T](obj: T): string` but I can't have a `seq[T]`. I also thought about tagged unions but as far as I know these can't be easily extended. Now on to my question. I tried this with a list of books and a for loop: type Book = ref object title: string var books = @[ Book(title: "War and Peace"), Book(title: "Of Mice and Men"), Book(title: "Moby Dick") ] titleReaders: seq[proc(): string] for i in 0..2: let w = proc(): string = books[i].title echo "Getter called inside loop: ", w() titleReaders.add(w) for tr in titleReaders: echo "Getter called outside loop: ", tr() Run Link: <https://play.nim-lang.org/#ix=3zRL> Here the closure inside the for loop also captures the loop variable `i` which equals 2 once the loop has finished. So all my title getters return "Moby Dick". (And it's also the same with a `for b in books` type of loop.) Is there a way to capture "the book itself" inside the loop, basically resolving one level of reference? I thought maybe with `addr` or `[]` but I couldn't get it to work. (I guess I could also write an alternative loop as a macro that expands into separate statements but I would rather stick to built-in loop constructs.)