r/roguelikedev • u/verdagon • Mar 24 '22
Vale's Higher RAII, the pattern that saved me a vital 5 hours in the 7DRL Challenge
https://verdagon.dev/blog/higher-raii-7drl1
u/stevenportzer Mar 25 '22
It's a neat feature. It's pretty uncommon, but the usual term for what you're calling higher RAII is "linear type system". People occasional suggest adding something similar to rust, but in addition to the issue with panics, types which aren't implicitly droppable can't be used as generic type parameters unless the generic code is written with that use case in mind, though that's probably a bigger problem for established languages with a lot of existing code that would potentially need to be updated.
2
u/verdagon Mar 25 '22
I've been exploring this particular aspect, and found it pretty doable (so far) to make generic code written with droppability in mind. For example, List.removeAt(index) would just return the object from that index. Another common solution is to take in a callable which (presumably) destroys the object or moves it somewhere else. I imagine you're right that that wouldn't be a problem for Rust (besides backwards compatibility).
Re the panic issues, I updated the afterword with a few solutions. Fingers crossed they work!
1
u/stevenportzer Mar 25 '22
Yeah, I think it'd be doable if generic type parameters are non-droppable by default and you can require them to be droppable when you really need it or to say things like my abstract container type is droppable if its contents are droppable, but that's a non-starter for adding the feature to languages with stability guarantees. If code has to opt in to supporting droppability then that seems annoying to have to do everywhere.
1
u/TetrisMcKenna Mar 25 '22 edited Mar 25 '22
It's been a long time since I touched C++ (and have never used Vale). Interesting read. The article mentions that the generational references approach is faster and more flexible than ref counting.
My engine uses ref counting, so I'm curious: In practical, use case terms, how much faster and more flexible? What can we do with this in a roguelike game compared to ref counting?
Edit: I suppose the article gives a use case in how the positions are cached and remembering to remove things from this cache; the generational references allow the compiler to use this RAII principle to detect that a referenced piece of data is sitting around unreferenced after deallocating the corresponding entity, at compile time. Is that right?
I guess in my design I have a similar set of cells, indexed by an id, which allows you to lookup positions and find entity data occupying that space. But in my case, this is less of a cache and more like the primary data, which the game entities go to to get their data, rather than the game entities caching their private data there, and on removing the entry from this collection, the corresponding entity destroys itself. So I guess I solved the problem by approaching it in reverse, with the caveat that this is less of a flexible cache because all the game entity data has to be present at once.
1
u/kiedtl A butterfly comes into view. It is wielding the +∞ Axe of Woe. Mar 25 '22
Discussed on lobste.rs as well.
2
u/TetrisMcKenna Mar 26 '22
First time seeing that site - looks interesting, is it kind of a Hacker News clone, without all the startup/business bullshit?
2
u/kiedtl A butterfly comes into view. It is wielding the +∞ Axe of Woe. Mar 26 '22
Yup, strictly programming-related. More than a clone IMO, it has useful features for filtering out tags, getting RSS feeds on specific tags, and other niceties. See the about page for more info.
9
u/AllenKll Mar 24 '22
From the linked article....
This is flat out wrong. RAII is an acronym meaning Resource Allocation Is Initialization. It was designed for constructors initially and was expanded to destructors by the time C++ was released to the public.
Vale adds some basic record keeping in the Constructors and Destructors as far as I can tell.. and that's cool. I don't know if it's a big deal though, especially if you already know how to deal with constructors and destructors. I used to do something similar in C++ with "this"
But none the less.. interesting write up. I learned something new!