Closed cactusdualcore closed 1 year ago
Another way to solve the problem I had is to convert return an owned value from the function passed to map
i.e. a PathBuf
in this case.
let mapped = iter_of_entries.map(|e| e.path().to_path_buf());
foo(mapped);
This allocates a new PathBuf
for every entry. These already contain PathBuf
s with identical contents though, so this really just does a lot of unnecessary work.
There is the newtype pattern for dealing with such cases.
struct MyDirEntry(pub DirEntry);
impl AsRef<Path> for MyDirEntry {
fn as_ref(&self) -> &Path {
self.0.path()
}
}
foo(iter_of_entries.map(MyDirEntry))
This does not allocate unnecessary memory, but I personally find this awkward and overengineered in this specific case, because AsRef
is incredibly straightforward to implement.
I am sorry, I didn't look through the issues before I made this PR. It seems this was declined before in #146 and if this PR is closed, I will respect that immediately.
For now I will keep this PR open though, because I would like present a final argument for my position. The issue that asked for this feature was closed, because
A DirEntry is more than a path, so it seems inappropriate to impl AsRef
I don't think this contradicts the semantics of AsRef
. The documentation of std::borrow::Borrow
says
If generic code merely needs to work for all types that can provide a reference to related type
T
, it is often better to useAsRef<T>
as more types can safely implement it.
This implies that AsRef
marks types that can provide a reference to their generic Argument. I think DirEntry
fits this understanding of what types should implement the trait.
My reasoning in #146 still applies. I admit the std docs aren't totally clear on whether or not an AsRef
impl here makes sense or not, but that cuts both ways. IMO, it's weird.
Also, you can seemingly achieve your original goal with DirEntry::into_path
.
I was working on another project with a function roughly like this
Somewhere else I tried calling this function with an iterator of
DirEntry
sThis does not work, because
DirEntry
does not implementAsRef<Path>
, butPath
does. So I tried thisThis does not compile, because
DirEntry::path()
returns a reference to the entry, which does not exist after themap
The thing that works is thisIt works, because the entries are now collected in a
Vec
and the closure's argument is already a reference. This is suboptimal, because it requires the user to allocate a vector that is used exactly once to call a function that doesn't want aVec
.