CRTP thoughts, named arguments DIP review, DConf videos now on youtube
Posted 2019-06-10
Blog
Articles- terminal.d gets clipboard functions, ldc 1.20 out.
- DConf keynote speaker announced: Lua architect Roberto Ierusalimschy, Named args DIP discussed
- February 3, 2020
- Adam's terminal suite explained
- Understanding mixin templates, terminal.d improvements
- My attribute-by-default proposal. Also dmd 2.090 came out.
- DConf 2020 announced: June 17-20 in London. @safe by default debated. Adam did: Android, JNI, WebSocket in arsd libs
- tar.xz, --DRT tip, dom bug fixes, more Android and JNI, link to old phobos docs
- LDC 1.19 - Android, AVR. My rant on tests, update on JNI and COM.
- Walter's string interpolation proposal is OK but not great. My Android thing nearing beta release. dub downtime explained.
- Android project update, introduction to arsd.jni
- New pattern about interface contracts
- Adam shares Windows console secrets - DO NOT USE chcp!!
- Adam's rant on benchmarks
- Socket tutorial
- November 4, 2019
- October 28, 2019
- arsd package updates, forum nonsense
- Update on Android
- Adam does iOS "goodbye world"
- September 30, 2019
- D turns 20, Adam rants on software freedom
- Named arg DIPs and my thoughts on code organization
- September 9, 2019
- I wrote about mixin templates vs string mixins on Stack Overflow
- August 26, 2019
- Bug bounty in D again - my hot take, on reusing code, a fun picture, my tentative plan for the next month
- Time invested is worth a lot
- cgi.d's new scheduler, static this tricks
- July 29, 2019
- July 22, 2019
- Solving vs managing problems
- A big week in the arsd repo
- July 1, 2019
- June 24, 2019
- June 17, 2019
- CRTP thoughts, named arguments DIP review, DConf videos now on youtube
- musings on hybrid CT/RT tests, some more progress on new web framework
- a little more webassembly
- May 20, 2019
- Adam's string interpolation proposal
- DMD 2.086 live, GCC 9 with D support formally released, DConf coming soon, links to posts on builder pattern and disallowing implicit conversions with templates, and 2d array op overloads
- template constraint error improvements coming?
- dmd 2.086 beta, dstep 1.0 released, Adam works on memory usage
- obj-c and webassembly report, tips on is expressions linked.
- new ldc, new dmd, dpp on the blog
- D's future discussed in forums
- LDC beta, DConf blog link, Adam introduces gamehelpers.d
- March 18, 2019
- LDC 1.15.0-beta1, responsive design rant
- dmd 2.085.0 released
- Obj-C interop and D without druntime code to copy/paste
- dmd beta, more info coming next time, demo of new web framework initial prototype
- automatic web interface discussion, reflection tips and tricks
- Adam busy with weather and a move, lots of community announcements
- January 28, 2019
- Working on official blog 2018 retro, C++ new wrapped, dmd reading zips?
- dmd obj-c growing, Adam static foreaches an interface to RPC
- dmd 2.084, hope for future, but busy non-D week for me
- IDE tools released, my cgi.d gets new features
- DConf announced, tip, Adam rants: mouse trap
- This Week in D is back!
My thoughts on the potential of the curiously recurring template pattern in D
Core D Development Statistics
In the community
Community announcements
See more at the announce forum.
Tip of the Week
If you have default behavior that the user can override, a common solution is to use a class with runtime polymorphism. The rest of your code can simply use the base class and the user can customize the behavior at construction time by providing an instance of their class instead. D supports this paradigm well, at least when the compile-time structure is known.
But, what if there is compile time knowledge needed? For example, if you are working with arbitrary, user-defined types:
With static foreach, we could define individual virtual overloads for a closed set of types, but that cannot expand to new types. With runtime variadics and delegates, we can handle new data types, but lose compile-time information in the base class implementation. Regular virtual methods won't help much.
We could use a template mixin with default implementations, and delegate to it:
Great! ... but the base class itself can't see any of that. You can pass Child instances to templates that can see it, but Base isn't one of those.
But, what if it was?
This is called the "curiously recurring template pattern", or CRTP. It was (actually pretty accidentally) discovered in C++ in the 90's and lets the base class see its own child at compile time, providing the possibility of static polymorphism.
With this, we don't need the mixin template anymore, and can instead put the default behavior directly into the base class.
Now we have a mix of arbitrary template specialization and overriding as well as traditional OOP inheritance. We can provide a mix of methods and templates to let the user control the whole class' behaviour and it is open to any new types we need to pass while keeping all compile time data available. Pretty cool stuff.
The downside though is the D language will not let us actually use the override keyword on templates, meaning you must get the names and arguments right or face either silent, unintended behavor (you got the name wrong) or loud, unhelpful error messages out of dmd itself (you got the arguments wrong, but the errors will apper to come from inside Base and barely even tell you what is actually expected). As a base class author using this technique, you'll have to be sure to carefully document the signatures and help your users along, reminding them of the necessity of the generic forwarder function too.
Thankfully, ddoc processors will be able to help your users to some extent, since at least the pseudo-virtual functions will be listed inside the base class too, giving you a reasonable place to write those docs.
Moreover, it is possible to have the base class use compile-time reflection to provide better error messages for its own children. Perhaps a user-defined @Override attribute could help catch such mismatches with static assert as well. I haven't had time to play with this myself yet, but I can't think of a reason why it wouldn't work, though I don't think it would be quite as nice as we get for runtime virtual polymorphism.
Another thing to keep in mind is that if you forget to cast this to the child class in a base, you won't actually call the "overridden" function. I can't think of any way to help with this except to say "don't do that". (You can also call your regular virtuals through the cast too, and by doing so possibly help the compiler in devirtualizing those calls for a small performance boost.)
And lastly, if the base class isn't written with this in mind, the pattern will not work. You want to suggest your users make the child classes final. But there is still the possibility of overriding other virtual methods and using regular substitution, so this may be an unnecessary restriction in some cases.
In any case, I had never found a use for the CRTP in the past with my own code, but am now exploring the possibilities of it in the new web framework I'm working on and I think there is a lot of potential that I don't see other D programmers doing much with. Here's hoping I'm actually seeing something they haven't :)
If you have any good uses of it, or superior alternatives, I wanna hear! Make a thread on forum.dlang.org, ping me (adam_d_ruppe) in #d on freenode IRC, or email me destructionator@gmail.com and I should see it and we can chat.
What Adam is working on
The tip of the week came out of me wanting to solve this problem for the new web framework: how can I provide sane out-of-the-box defaults for working with arbitrary user types while still letting the user change that behavior?
Of course, there are a lot of options. I could decorate types with user-defined attributes and have the reflection react to them. I could check for the existence of special methods on the types. I do many of those things, but I also wanted a centralized place for users to change behavior, in the interest of model/view separation and easier unittesting in certain situations.
This led to the WebPresenter class. It converts normal D types, return values and exceptions, to html+http responses - a capability I have had for many years, but never customizable like this.
If you want to change the default, you define a child class using the CRTP technique and override functions. So far, I am liking it. More as it develops.
DConf 2019
I also watched the DConf videos, which are on the DLF youtube channel. I don't have a lot to say yet though, I'll come back to it.