Not mentioned and IMO important is that adding Default to the struct M means users would be able to create an M directly, without going through the constructor function M::up(). Furthermore, backwards compatibility would imply that the Default trait implementation can’t be removed in the future.
If the goal is only to reduce typing, then I think a standalone fn default<'a>() -> M<'a> function would work just as well. That would be usable in a struct literal in the same module, and wouldn’t expand the API contract.
You’ve given up the ability to have the compiler take you through all those initialisation points, and you risk missing the places where you do want to add something different from the “default”.
Besides, what does “default” mean, anyway? It’s often neutral “with respect to some other operation”, in which case the abstraction you’re reaching for is “monoid”.
Not mentioned and IMO important is that adding
Default
to thestruct M
means users would be able to create anM
directly, without going through the constructor functionM::up()
. Furthermore, backwards compatibility would imply that theDefault
trait implementation can’t be removed in the future.If the goal is only to reduce typing, then I think a standalone
fn default<'a>() -> M<'a>
function would work just as well. That would be usable in a struct literal in the same module, and wouldn’t expand the API contract.That’s a great point, I did not think of that.
Except for
#[derive(Default)]
for struct that contains fields of this type.You’ve given up the ability to have the compiler take you through all those initialisation points, and you risk missing the places where you do want to add something different from the “default”.
Besides, what does “default” mean, anyway? It’s often neutral “with respect to some other operation”, in which case the abstraction you’re reaching for is “monoid”.