I am trying to use .join on T: PartialEq, which is giving errors

#[derive(Debug, PartialEq)]
pub enum Comparison {
Equal,
Sublist,
Superlist,
Unequal,
}

pub fn sublist<T: PartialEq>(_first_list: &[T], _second_list: &[T]) -> Comparison {
let _first_list_string = _first_list.join(" ");
println!("{}", _first_list_string);
}

#[test]
#[ignore]
fn huge_sublist_not_in_huge_list_2() {
let v1: Vec = vec![0; 1_000_000];
let mut v2: Vec = vec![0; 500_000];
v2.push(1);
assert_eq!(Comparison::Unequal, sublist(&v1, &v2));
}

I want to convert the &[T] into a big string using .join method but I am getting these issues.

the method join exists for reference &[T], but its trait bounds were not satisfied

method cannot be called on &[T] due to unsatisfied trait bounds

note: the following trait bounds were not satisfied:
[T]: std::slice::Join<_>rustc(E0599)

main.rs(157, 42): method cannot be called on &[T] due to unsatisfied trait bounds

the method join exists for reference &[T], but its trait bounds were not satisfied
the following trait bounds were not satisfied:
[T]: Join<_>rustcE0599

I am new to rust and not able to figure out what is going wrong... Can anyone please help me to convert the slice into string?

What are you expecting to get from _first_list.join(" ")? The only thing you know about T is that you can compare it with itself, but join will have to somehow build a string - how?

2 Likes

For instance i need output of vec![0; 1_000_000]; as "0 1 2 .... 1_000_000" but i am not able to figure out how to do it.

If you want to be able to print for any arbitrary T, it must have a trait bound which allows it to be convertible to a string. Two common such traits are Debug and Display. For numbers, you can use either - in general if you want to print something Display makes more sense, while Debug is as the name suggests more for debug output.
So, in your case, you need a trait bound of T: PartialEq + Display. Then you can do something like:

let first_list_str = first_list.into_iter().cloned().map(Display::to_string).collect::<Vec<_>>(); 
let first = first_list_str.join(" ");
println!("{}", first);
2 Likes

This will not work - one must either collect to the intermediate vector first, or use something like Itertools::join.

Sorry, my bad.

Thanks for the help I guess I understood that I need format the type and use it

#[derive(Debug, PartialEq)]
pub enum Comparison {
Equal,
Sublist,
Superlist,
Unequal,
}

pub fn rem_first_and_last(value: &str) -> &str {
let mut chars = value.chars();
chars.next();
chars.next_back();
chars.as_str()
}
pub fn form_string<T: std::fmt::Debug> (_first_list: &[T], _second_list: &[T]) -> bool {
let mut _first_list_string = format!("{:?}",_first_list);
let mut _second_list_string = format!("{:?}", _second_list);

_first_list_string = rem_first_and_last(_first_list_string.as_str()).to_string();
_second_list_string = rem_first_and_last(_second_list_string.as_str()).to_string();

return _second_list_string.contains(_first_list_string.as_str())

}

pub fn check_equal<T: std::fmt::Debug> (_first_list: &[T], _second_list: &[T]) -> bool {
let mut _first_list_string = format!("{:?}",_first_list);
let mut _second_list_string = format!("{:?}", _second_list);

_first_list_string = rem_first_and_last(_first_list_string.as_str()).to_string();
_second_list_string = rem_first_and_last(_second_list_string.as_str()).to_string();

return _second_list_string == _first_list_string.as_str()

}

pub fn sublist<T: std::fmt::Debug>(_first_list: &[T], _second_list: &[T]) -> Comparison {
if check_equal(_first_list, _second_list) {
return Comparison::Equal
} else if _first_list.len() < _second_list.len() && form_string(_first_list, _second_list) {
Comparison::Sublist
} else if _first_list.len() > _second_list.len() && form_string(_second_list, _first_list) {
Comparison::Superlist
} else {
Comparison::Unequal
}
}

This solved everything I need and I passed all the test cases thanks for the help!

You can check my question and solution on this Exercism