Pre-RFC: Take trait with impl for Default


#1

Not sure if this has been proposed before, but it would be nice to have a Take trait as defined below:

trait Take {
    fn take(&mut self) -> Self;
}

This is inspired by the Option.take method, but to make it even more useful there could be an implementation for types which implement Default:

impl<D: Default> Take for D {
    fn take(&mut self) -> Self {
        mem::replace(self, Default::default())
    }
}

My motivation was wanting a way to check and clear a boolean flag in one step, then I thought the idea was generic enough it could apply to any Default type.


#2

A similar method also exists as Cell::take. Looking at the impls of Default in std, this looks like it will work pretty much everywhere and be quite convenient.

Downside is if default is expensive and you’re just trying to move out quickly. Then you’re wasting time computing defaults when you don’t actually need them. Option and Cell don’t have this problem because the defaults are cheap.

EDIT: Actually, I don’t think &mut Cell is sensible to its purpose, so Cell::take has a different definition.


#3

Maybe the implementation should be on D : Default + Copy so that it will only be default implemented for Copy types that also implement default?


#4

A similar proposal previously:


#5

I’d deprecate Option::take instead.

mem::replace is usable enough.

Additinally, there’s nothing specific to “object” or to construction in this operation to make it a method.

So if we will have this operation, I’d prefer it to be global in mem namespace:

mem::take<T: Default>(ptr: &mut T) { ... }

(Same way forget or drop are global functions, not instance methods.)