In this post:
- What this all is
- My long-term goals
- Short-term avenues of improvement
- While discussing an irritating limitation, I get so irritated that I go deal with it
- A formidable breakdown of short-term goals
- Which of those goals I feel are in scope for this week
- The plan
So, last weekend, I started working on attempting to port Ghosts of Departed Proofs from Haskell to Rust. It appears that, by now, I've got the core mostly working, and I'm focusing on proving this out by trying to implement Ghosts functionality for sorted Vec and Iterator.
So far as that, my plan there is to implement functionality for every kind of stdlib iterator that makes sense in the context of "preserving a sorted invariant", then create a Merged iterator struct. Thinking over how I'd implement such a thing earlier, I concluded that the implementation would actually be kind of obnoxious, so I'll content myself with just laying the groundwork for now.
In terms of the quality of the code right now, there are a few issues and open questions:
- I've just started documenting things; I want to have some really thorough documentation in there.
- There are some things I'm not sure about with the macro matches I'm doing. Like, should there by optional trailing semicolons?
- I can't point at anything that I know I could do better, but the macros I've written look kind of janky. One of them has nine match arms, and three of them are just so a different three get triggered with or without a trailing comma.
In terms of stdlib code to write special handling for:
- I've already written a conversion for Cloned.
- Several structures need unconditional conversions:
- Some have straightforward conversions:
- Some have somewhat more elaborate conversions:
- Enumerate (products the name with DefaultCmp.)
- Rev (wraps the Name in a Reverse. Double Reverse should allow for cancellation. Reverse should propagate inward through products.)
- Zip (given two arbitrary names, uses their product, which is also a name.)
There are also a bunch of traits. The way I'm doing things currently, I can't have blanket impls, but I might change that. The basic issue is that, until I changed it literally as I was writing this, I was using a single structure for every role in this code, which turns out not to work all that well in terms of blanket impls. The impls stop conflicting, though, if I have different container types for different kinds of object, so that turns out to be okay. Now, I can't do a blanket implementation of FromIterator because not all containers preserve insertion order, so that's going to be a piecemeal kind of thing.
I might also want to change the way I do products of names; I'll have to see if there are any disadvantages to using simple tuples.
I mentioned earlier that the implementation of Merged seemed obnoxious. Basically, it's a pair of peekable, potentially double-ended, fused iterators, along with a function. If either iterator is exhausted, it must be discarded and not consulted again.
I just realized that Enumerate, Rev, and Zip have some more issues: Enumerate and Zip need to have a corresponding set of function combinators, as does Rev.
The stuff I feel like doing goes roughly in order of:
- Document existing code
- Implement the combinators mentioned above
- Implement the unconditional conversations
- Implement blanket traits
- Implement the straightforward conversions
- Design Merged
- Make decisions about what to accept in the macros
- Streamline the macro definitions
- Implement Merged
This is probably not entirely honest, in that I've got a good idea of how I want Merged to look, but I'd rather have more experience with the code before I commit to it.
I think I'll break down the tasks for the two middle posts in this week thus:
- First, document as much as I can, and summarize the stuff I documented.
- Second, implement whatever. There are probably some dependencies I glossed over up there, so I'll really tackle those in whatever order ends up making sense. Probably do the blanket traits early, because those don't really rely on anything else that I can think of.
Next time, EDIT: WHOOPS I DIDN'T FILL THIS IN FOR TWO DAYS I look into improving the documentation, and then the overall API.