-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Not clear that EntryMap can be used in generic contexts #2
Comments
Interesting. I wonder if associated lifetimes would help. I'm looking into this now. |
The following appears to work: extern crate eclectic;
use eclectic::*;
use std::hash::Hash;
pub fn categorize<D, F, M>(data: D, mut f: F) -> M where
D: IntoIterator,
F: FnMut(&D::Item) -> M::Key,
M: Default + for<'a> EntryMap<'a>,
M::Key: Eq + Hash,
M::Value: Default + Extend<D::Item>,
{
let mut map = M::default();
for datum in data {
match map.entry(f(&datum)) {
Entry::Vacant(e) => e.insert(M::Value::default()),
Entry::Occupied(e) => e.into_mut(),
}.extend(Some(datum));
}
map
} |
With the entry API I just added in 0.0.3, this can be written as: extern crate eclectic;
use eclectic::*;
use std::hash::Hash;
pub fn categorize<D, F, M>(data: D, mut f: F) -> M where
D: IntoIterator,
F: FnMut(&D::Item) -> M::Key,
M: Default + for<'a> EntryMap<'a>,
M::Key: Eq + Hash,
M::Value: Default + Extend<D::Item>,
{
let mut map = M::default();
for datum in data {
map.entry(f(&datum)).or_insert_with(M::Value::default).extend(Some(datum));
}
map
} |
There's also no need for the key to implement |
Oh yeah sorry that was legacy from the port. See: http://www.reddit.com/r/rust/comments/38oa85/more_generic_partition_method_how_would_it_look/ I'm confused that you can talk about the associated types of a |
Yeah, that's kind of mysterious. Might be a bug in rustc that only applies that restriction to the |
Although, to be fair, those associated types are actually defined on |
(Adding something like |
I don't think this is actually instantiable: extern crate eclectic;
use eclectic::*;
pub fn categorize<D, F, M>(data: D, mut f: F) -> M where
D: IntoIterator,
F: FnMut(&D::Item) -> M::Key,
M: Default + for<'a> EntryMap<'a>,
M::Value: Default + Extend<D::Item>,
{
let mut map = M::default();
for datum in data {
map.entry(f(&datum)).or_insert_with(M::Value::default).extend(Some(datum));
}
map
}
#[test]
fn test() {
use std::collections::*;
let x: HashMap<i32, Vec<i32>> = categorize(vec![1,2,3,4,5,6,7], |&x| x % 4);
let y: BTreeMap<i32, VecDeque<i32>> = categorize((1..10).take(10), |&x| x);
}
|
Hmm. I don't know why that bound is a requirement. Investigating... |
It seems to me that for<'a> collections::vec::Vec<i32>: 'a should be met, as |
The code around |
cc me |
Note that we will want to replace the lifetime parameter in |
After rust-lang/rust#27096 landed, the following now works: extern crate eclectic;
use eclectic::map::EntryMap;
pub fn categorize<D, F, M>(data: D, mut f: F) -> M
where
D: IntoIterator,
F: FnMut(&D::Item) -> M::Key,
M: Default + for<'a> EntryMap<'a>,
M::Value: Default + Extend<D::Item>,
{
let mut map = M::default();
for datum in data {
map.entry(f(&datum)).or_insert_with(M::Value::default).extend(Some(datum));
}
map
}
#[test]
fn test() {
use std::collections::*;
let x: HashMap<i32, Vec<i32>> = categorize(1..8, |&x| x % 4);
assert_eq!(x[&0], [4]);
assert_eq!(x[&1], [1, 5]);
assert_eq!(x[&2], [2, 6]);
assert_eq!(x[&3], [3, 7]);
let _: BTreeMap<i32, VecDeque<i32>> = categorize(1..10, |&x| x);
} |
Daaang 👏 |
I think it needs HKT or something loopy like that. For instance I tried implementing a super generic "categorize":
But it's not clear that a lifetime can be supplied for EntryMap.
The text was updated successfully, but these errors were encountered: