The trait Default/Extend is not implemented for

Hi,

I'm currently trying out Rust by writing a deduplication tool. Since I come from a FP/scala background, I like writing in the functional style with collections and higher-order-functions.
I use walk_dir for recursively reading in a root directory, and then I'd like to partition the iterator into files and folders. Since the compiler fails to infer types returned by the partition function it asks me to state the types. I'm getting two errors which I think are related to this type annotation and I cannot find anything helpful when googling for that:
error: the trait core::default::Default is not implemented for the type std::fs::WalkDir [E0277]
error: the trait core::iter::Extend<core::result::Result<std::fs::DirEntry, std::io::error::Error>> is not implemented for the type std::fs::WalkDir [E0277]

code in rust playpen: Rust Playground

What is wrong here? I do not understand why and how I need to implement Default / Extend?

Thank you for your answers.

best,
ingvar

Your error is to think that partition returns two iterators, it does not. You iterate over b and partition returns two collections of DirEntry. See Rust Playground.

Also your iterator b already iterates over directories, so I don't see the point to partition over directories (only the first collection will be filled). But maybe I'm wrong because I don't know well this API.

HTH

2 Likes

Hi ptalbot,

Thank you for your fast answer, it works now and returns both folders and files.

I see, I'm used from scala that the collection returned is always of the same type as the input collection.

Just to understand better: In the documentation of iterator, the signature of partition is:
fn partition<B, F>(self, f: F) -> (B, B)
where F: FnMut(&Self::Item) -> bool, B: Default + ExtendSelf::Item

So, somewhere there is a Default defined that specifies to use Vec as output collection?
Could I implement Default and provide it at call site in order to use another output collection? For example, there might be a situation where you want a Set instead?

thanks

regards,
ingvar

Use pattern matching:

let (files: Set<_>, dirs: Set<_>) = iterator.partition(|&a| ...);

Or type ascription:

let result: (Set<_>, Set<_>) = iterator.partition(|&a| ...);

Or you can try type specification:

let result = iterator.partition::<Set<_>, _>(|&a| ...);

Nothing above is tested, although, just got it out of my head.

For generic purposes, nothing explicitly specify that partition returns a collection. But if you closely look at the bounds of B, you see that it must implements Default and Extend, the first means that B has a default state, here an empty vector, and the second that B can be extended with a new element. The second implicitly tell you that you probably want B to be a collection, but any types that implement both traits are ok. So Vec, BTreeSet, are ok, for an exhaustive list, see the doc.

Then, as kstep said, B is infered from the context, and if the context does not give information on B, you must give additional informations to the type checker.

the second one works, cool!

thanks for the clarification. I read the doc of Extend but the description was not clear: "A type growable from an Iterator implementation". In fact, from how you describe it, it sounds a bit like a Monoid in functional programming: a) have a neutral empty/zero value and b) allow concatenation.
But the docs read very differently, also the descr of the extend method: "Extend a container with the elements yielded by an arbitrary iterator".

It probably can be understood as B being a monoid, but not much mathematical terminology is used in the Rust collection library, it certainly should however. To understand the doc, consider:

  1. T: IntoIterator<Item=A>
  2. For example: impl<T> Extend<T> for Vec<T>

(1) means that the elements yielded by the "arbritray iterator" must be of the same type as the ones in Self. (2) gives you an example for Vec<T> where Item=T, and so, Vec<T> is extended by elements of type T so everything makes sense.

Everything is a bit different, but it's clear now.

Although in many areas it's quite nice and shiny, I believe the documentation could use a helping hand. Maybe I start contributing, because newcomers see best where things are not as clear as they should be.

Thanks!