[rust-dev] Will smart-pointer deref operator allow making iter::ByRef more generic?

2014-02-03 Thread Palmer Cox
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


Re: [rust-dev] Will smart-pointer deref operator allow making iter::ByRef more generic?

2014-02-03 Thread Bill Myers
I don't think so, because the fact that the particular instance of T implements 
the Deref trait cannot have any effect on the decorator code, since it's not in 
the bounds for T.

What instead would work is to change the language so that if type Type 
implements Trait and all Trait methods take self or mut self (as opposed to 
by value self or ~self), then an implementation of Trait for 'a mut Type is 
automatically generated (with the obvious implementation).

Likewise if all Trait methods take self, then an implementation of Trait for 
'a Type is also automatically generated.

Then what you want to do will just work without the need of any wrapper or 
special syntax.

One could then, as an additional step, automatically generate an implementation 
of Trait for MutDerefType if Trait is implemented by mut Type (possibly due 
to the above technique), but this would not be required for the example.
   
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev