How to use std::cmp::Reverse with binary_search_by_key? Example: Rust-Playground
The documentation to Rust's Vec::binary_search_by_key says:
Assumes that the slice is sorted by the key, for instance with sort_by_key using the same key extraction function.
In the minimal example below, I am using the same extraction function -- but no luck.
use std::cmp::Reverse;
fn main() {
let mut v = vec![1, 2, 3, 4, 5];
v.sort_by_key(|&num| Reverse(num));
println!("{:?}", v);
let index = v.binary_search_by_key(&1, |&num| Reverse(num));
println!("Res: {:?}", index);
}
This complains about mismatched types: "expected integer, found struct std::cmp::Reverse".
error[E0308]: mismatched types
--> src/main.rs:8:51
|
8 | let index = v.binary_search_by_key(&1, |&num| Reverse(num));
| ^^^^^^^^^^^^ expected integer, found struct `std::cmp::Reverse`
|
= note: expected type `{integer}`
found struct `std::cmp::Reverse<{integer}>`
Careful inspection of the function signature gives the answer.
pub fn binary_search_by_key<'a, B, F>(
&'a self,
b: &B,
f: F
) -> Result<usize, usize> where
B: Ord,
F: FnMut(&'a T) -> B,
B is the return value of the function, and also the first argument (after &self).
Therefore we have to add Reverse to the first argument as well:
v.binary_search_by_key(&Reverse(1), |&num| Reverse(num))
Related
I need the trait XYZ to define a method that allows iterating over some set of integers. This set of integers is defined either by a backing Vec or by a Range<usize>. However, I run into various (lifetime or type) issues depending on how I define the XYZIterator type that is supposed to unify these Iterators over Vec/Range.
The backup solution would be to allocate and return Vecs, but I wondered whether there was a way without cloning/allocating memory.
type XYZIterator = Box<dyn Iterator<Item = usize>>;
trait XYZ {
fn stuff(&self) -> XYZIterator;
}
struct Test {
objects: Vec<usize>,
}
impl XYZ for Test {
fn stuff(&self) -> XYZIterator {
Box::new(self.objects.iter())
}
}
struct Test2 {}
impl XYZ for Test2 {
fn stuff(&self) -> XYZIterator {
Box::new((1..4).into_iter())
}
}
fn main() {
let t1 = Test {
objects: vec![1, 2, 3],
};
let t2 = Test2 {};
t1.stuff().for_each(|x| println!("{}", x));
t2.stuff().for_each(|x| println!("{}", x));
t1.stuff()
.filter(|x| x % 2 == 0)
.for_each(|x| println!("{}", x));
t2.stuff()
.filter(|x| x % 2 == 0)
.for_each(|x| println!("{}", x));
}
error[E0271]: type mismatch resolving `<std::slice::Iter<'_, usize> as Iterator>::Item == usize`
--> src/main.rs:12:9
|
12 | Box::new(self.objects.iter())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference
|
= note: expected type `usize`
found reference `&usize`
= note: required for the cast to the object type `dyn Iterator<Item = usize>`
Your code has two issues:
In the implementation of XYZ for Test1, you return the iterator self.objects.iter(). Vec::iter iterates over references to the objects, not objects themselves, so this is an iterator over &usize, which doesn't match the return type. You should have gotten an error about this. It's easy to fix though: self.objects.iter().copied() will copy each element out of the reference.
In type XYZIterator = Box<dyn Iterator<Item = usize>>;, since there is no lifetime in the trait object, it defaults to 'static - that is, your iterator can live forever. But that's not the case with the vector iterator - it has a reference to the vector is iterating over. This is where you are having lifetime issues.
The solution is to give the XYZIterator type a lifetime:
type XYZIterator<'a> = Box<dyn Iterator<Item = usize> + 'a>;
And alter the traits and trait implementations to use the lifetime.
Also consider altering your type or function to accept any T: Iterator<Item=usize>; it will then accept any iterator that produces usizes
I encountered an error when trying to use a function get_even_numbers() to borrow a vec v by passing it in by reference &v instead of by value v.
fn get_even_numbers(v: &Vec<i32>) -> Vec<i32> {
v.iter().filter(|x| x % 2 == 0).collect()
}
fn main() {
let v: Vec<i32> = (0..10).collect();
let even: Vec<i32> = get_even_numbers(&v);
println!("Even numbers: {:?}", even);
}
error[E0277]: a value of type `Vec<i32>` cannot be built from an iterator over elements of type `&i32`
--> src/main.rs:2:37
|
2 | v.iter().filter(|x| x % 2 == 0).collect()
| ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=&i32>`
|
= help: the trait `FromIterator<&i32>` is not implemented for `Vec<i32>`
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
note: required by a bound in `collect`
Why does the above give an error, but passing it in by value does not, as shown below?
fn get_even_numbers(v: Vec<i32>) -> Vec<i32> {
v.into_iter().filter(|x| x % 2 == 0).collect()
}
fn main() {
let v: Vec<i32> = (0..10).collect();
let even: Vec<i32> = get_even_numbers(v);
println!("Even numbers: {:?}", even);
}
Even numbers: [0, 2, 4, 6, 8]
I used .iter() inside the function when passing in by reference and .into_iter() when passing in by value, not sure if these are the correct functions to use.
Use v.iter().filter(|x| x % 2 == 0).cloned().collect(). That will (trivially) clone each of the &i32 references into actual i32 values.
I have a Reader that I want to prepend some bytes to, creating a Chain. Ideally I'd want to do this:
use std::io::{Chain, Read};
fn thingify<R: Read>(r: R) -> Chain<[u8; 3], R> {
let mut arr = [1u8, 2u8, 3u8];
// Modify arr here
return arr.chain(r);
}
But that throws a compiler error:
error[E0308]: mismatched types
--> test.rs:7:12
|
3 | fn thingify<R: Read>(r: R) -> Chain<[u8; 3], R>
| ----------------- expected `std::io::Chain<[u8; 3], R>` because of return type
...
7 | return arr.chain(r);
| ^^^^^^^^^^^^ expected array of 3 elements, found &[u8]
|
= note: expected type `std::io::Chain<[u8; 3], _>`
found type `std::io::Chain<&[u8], _>`
From what I understand, this seems to be because Read is implemented for slices rather than arrays, and somehow my array decays to a slice here.
But when I change the array in the return type to a slice and give it an explicit lifetime like so:
use std::io::{Chain, Read};
fn thingify<'a, R: Read>(r: R) -> Chain<&'a [u8], R> {
let arr = [1u8, 2u8, 3u8];
// Modify arr here
return arr.chain(r);
}
I just get another compiler error instead:
error[E0515]: cannot return value referencing local variable `arr`
--> test.rs:19:12
|
19 | return arr.chain(r);
| ---^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| `arr` is borrowed here
How can I transfer ownership of my array to the Chain so that I can return it? Is that simply not doable with a [u8]?
Because Read is implemented for &'_ [u8] but not for [u8; 3], the compiler automatically converts your array into a reference slice. This mean your array must be valid as long as the slice live so as long as the Chain live.
There are several solutions, you could ask to the caller a mutable slice, you could make it static if you want to be able to mutate it, if you don't you can make it const, if you need to resize it you need a Vec, etc...
use std::io::{stdin, Chain, Read};
fn a<R: Read>(arr: &mut [u8; 3], r: R) -> Chain<&[u8], R> {
arr.copy_from_slice(&[1, 2, 3]);
arr.chain(r)
}
fn b<R: Read>(r: R) -> Chain<&'static [u8], R> {
const ARR: [u8; 3] = [1, 2, 3];
ARR.chain(r)
}
fn main() {
let mut arr = [0; 3];
println!("{:?}", a(&mut arr, stdin()));
println!("{:?}", b(stdin()));
}
See:
Is there any way to return a reference to a variable created in a function?
In this example, the compiler can not infer the matrix type:
type Mat4x4<T> = [T; 16];
fn main() {
let m: Mat4x4 = [0.4323f32; 16];
println!("{:?}", m);
}
The working code is:
type Mat4x4<T> = [T; 16];
fn main() {
let m: Mat4x4<f32> = [0.4323f32; 16];
println!("{:?}", m);
}
Is this an expected act?
This is not a type inference issue:
type Mat4x4<T> = [T; 16];
fn main() {
let m: Mat4x4 = [0.4323f32; 16];
println!("{:?}", m);
}
Yields the following error message:
error[E0107]: wrong number of type arguments: expected 1, found 0
--> src/main.rs:4:12
|
4 | let m: Mat4x4 = [0.4323f32; 16];
| ^^^^^^ expected 1 type argument
The complaint here is that Mat4x4 is not a type, it's a template or blueprint to create a type.
An analogy would be that Mat4x4 is a waffle iron, and Mat4x4<f32> is a waffle that comes out of it. If you are served the waffle iron (with maple syrup on top, of course) you will likely be disappointed!
The same applies here: when you give the compiler the blueprint where it expects the final product, it signals you that it was not what it expected.
You can supply a dummy argument (_), and it will be inferred:
let m: Mat4x4<_> = [0.4323f32; 16];
You cannot omit required type parameters, but you can use _ to infer them:
let m: Mat4x4<_> = [0.4323f32; 16];
Alternatively, you could add a default type parameter so you could omit the <…> when the type T is exactly f32 (but this is not type inference, you still need to write Mat4x4<f64> explicitly).
type Mat4x4<T = f32> = [T; 16];
let m: Mat4x4 = [0.4323f32; 16];
I have this precise object and function definition:
pub struct Mep<Ins> {
instructions: Vec<Ins>,
}
impl<Ins> Mep<Ins> {
pub fn crossover<F>(parent0: &Mep<Ins>, parent1: &Mep<Ins>, mut random_point_generator: F) -> Mep<Ins>
where F: FnMut(usize) -> usize, Ins: Clone {/*Body omitted*/}
}
The function compiles fine, but I receive the same error even for an empty function definition when calling it:
tests/mep.rs:14:33: 14:34 error: expected type, found `|`
tests/mep.rs:14 let c: Mep::crossover(a, b, |x| rng.next_u32() % x);
I also tried different parameters:
pub fn crossover<F>(parent0: &Mep<Ins>, parent1: &Mep<Ins>, points: usize, mut random_point_generator: F) -> Mep<Ins>
where F: FnMut(usize) -> usize, Ins: Clone {}
It results in the same error:
tests/mep.rs:14:33: 14:34 error: expected type, found `3`
tests/mep.rs:14 let c: Mep::crossover(a, b, 3, |x| rng.next_u32() % x);
I am fairly new to rust and everywhere I look online discusses issues people have with obvious generics problems, but they aren't shared with my case as far as I can tell. What do I need to do to call this function?
Variable assignment in rust is done with an equals sign, not a colon. So your statement should be
let c = Mep::crossover(a, b, 3, |x| rng.next_u32() % x);
If you want to also specify a type, you need both the colon with a following type AND an equals sign with the expression afterwards:
let c: Mep<Ins> = Mep::crossover(a, b, 3, |x| rng.next_u32() % x);