Hi,
I was looking at some structs in Rust that implement the Decorator pattern
- structs that take some value, wrap it, and then provider the same
interface as the value that they are wrapping while providing some extra
behavior. BufferedReader is an example here - it takes another Reader and
provides buffering functionality while still presenting the same interface.
Anyway, I noticed that there seem to be two different patterns that are
being used in Rust to do this - some structs take ownership of the value to
be wrapped while other structs take a borrowed reference to the object to
be wrapped. Both approaches have advantages and disadvantages. If you take
ownership you have the advantage that the resulting struct is Send, however
if all you have is a reference to the object you want to wrap, it won't
work. The following, for example won't compile:
let mut r = File::open(Path::new(/)).unwrap();
let br = BufferedReader::new(mut r);
If the wrapping struct takes a reference, the example above will work.
However, the resulting struct won't be Send. So, in both cases, the result
is that some use-cases won't work.
I noticed that the iter module addressed this issue with the ByRef struct.
All Iterators that wrap other iterators take ownership of the value to be
wrapped. If you want to prevent that, you can use ByRef (which hold a
reference to the value to be wrapped) and pass it to the wrapping Iterator
which takes ownership of the ByRef instance as opposed to the iterator you
are wrapping. The problem with ByRef, though, is that it only works for
Iterators. Its possible to implement different versions of ByRef for other
types as well. However, this seems a bit tedious.
This is a relatively common and fairly useful pattern, so it would seem
that it would be nice to be able to support all of the use cases for all
types. Anyway, its my understanding that future plans for Rust call for a
custom derefence trait to be added to allow for the implementation of
custom smart pointers. What I was wondering if that trait would also allow
for making iter::ByRef into a smart pointer that could provide this type of
behavior for any type as opposed to just Iterators. If that's the case, it
seems like all of the structs that implement the decorator pattern could be
modified to take the value they are wrapping by value and let the caller
use the ByRef struct if they would prefer not to transfer ownership of the
value to be wrapped. The upsides are that it seems that this would allow
all use cases to be met and it would make all the Decorators consistent;
the downside is that it would making wrapping a borrowed reference a little
bit more verbose. I don't think that would be all that bad, though. This
doesn't look too bad to me:
let mut r = File::open(Path::new(/)).unwrap();
let br = BufferedReader::new(ByRef::new(mut r));
Thoughts? Things I'm wrong on?
Thanks,
-Palmer Cox
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev