allending/Kiwi — pull request #493 by sharplet (2014-04-03 09:33:31+00:00)
Title: Ensure let blocks are evaluated only once per example

This resolves #433.

1. Instead of holding a direct reference to its block, `KWLetNode` now turns it into a future (using https://github.com/mikeash/MAFuture).

2. When a node is evaluated, its pointer and all its children's pointers are assigned a reference to the future. The important difference here is that *the block still hasn't been evaluated*. Because it's now a future, the block isn't evaluated until the first time the future object is messaged, at which point the block is invoked and the message send is proxied to the real object.

That is, we now have **real lazy evaluation**, just like RSpec! Yay! 🎉

3. The let node tree is now unlinked, and the values reset, at the end of each example (rather than after the last example in a context, which was incorrect).

I'm still not 100% certain that this was the only solution. But figuring out the correct order in which to evaluate let nodes, in order to "simulate" lazy evaluation, was a big headache. Introducing futures made this problem go away by decoupling let node *tree* evaluation (assigning object references to let helper variables) from actual let *block* evaluation. So when the tree is evaluated we can just

![EVALUATE ALL THE THINGS](http://cdn.memegenerator.net/instances/500x/48059986.jpg)

without worrying about side effects. And then when a future is actually used the block is lazily evaluated as needed.

Hope that makes sense! 😅

---

If everyone's happy to go ahead with this, the question of the best way to import a third-party dependency still remains. I've just copied the source code from MAFuture `HEAD` into the tree for now, for testing. For CocoaPods, I've exported the code as a subspec. Would a git submodule be better for bringing in the source? Additionally, it's also bringing in a significant chunk of code that's still MRC, which doesn't make me super happy given the awesome progress recently on converting to ARC!