I'm trying to test some code which takes a reader. I've got a function:
fn next_byte<R: Read>(reader: &mut R) -> ...
How can I test it on some array of bytes? The docs say that there's a impl<'a> Read for &'a [u8], which would imply this should work:
next_byte(&mut ([0x00u8, 0x00][..]))
But compiler disagrees:
the trait `std::io::Read` is not implemented for the type `[u8]`
Why? I explicitly said &mut.
Using rust 1.2.0
You are trying to invoke next_byte::<[u8]>, but [u8] does not implement Read. [u8] and &'a [u8] are not the same type! [u8] is an unsized array type and &'a [u8] is a slice.
When you use the Read implementation on a slice, it needs to mutate the slice in order for the next read to resume from the end of the previous read. Therefore, you need to pass a mutable borrow to a slice.
Here's a simple working example:
use std::io::Read;
fn next_byte<R: Read>(reader: &mut R) {
let mut b = [0];
reader.read(&mut b);
println!("{} ", b[0]);
}
fn main() {
let mut v = &[1u8, 2, 3] as &[u8];
next_byte(&mut v);
next_byte(&mut v);
next_byte(&mut v);
}
Related
I am a beginner in Rust and am trying to create a Parser Combinator library in order to learn the ropes of the language. Very early on in this project I've gotten stuck. I want to have a Parser struct that holds the function used to parse data. Here is my attempt at implementing this.
struct Parser<I, O> {
parse: impl Fn(&Vec<I>) -> Option<(&Vec<I>, O)>
}
Unfortunately, as the compiler informs me, i can not use the "impl Trait" notation in this way. Another way I've tried is by defining a separate type variable for the type of the function itself, as below.
struct Parser<I, O, F>
where
F: impl Fn(&Vec<I>) -> Option<(&Vec<I>, O)>
{
parse: F
}
However, it seems redundant and unnecessary to have to provide the input, output, and function type, as the function type can be derived from the input and output. Also, the compiler gives me an error due to the fact that neither I or O are used.
I also considered Parser may have to be a trait rather than a struct. However I can't really wrap my head around what that would look like, and it seems like you would run into the same issue trying to define a struct that implemented the Parser trait.
Not a lot of context, but you I'll try doing it this way:
struct Parser<I, O> {
parse: Box<dyn Fn(&Vec<I>) -> Option<(&Vec<I>, O)>>,
}
fn main() {
let parser = Parser {
parse: Box::new(|x| {
Some((x, x.iter().sum::<i32>()))
})
};
let v = vec![1, 2, 3, 4];
let result = (parser.parse)(&v).unwrap();
println!("{:?}", result);
}
For some more suggestion I would look here: How do I store a closure in a struct in Rust?
I think all you need is std::marker::PhantomData to silence the error about unused generics. You can also make the code a bit more DRY with some type aliases. (I've replaced &Vec<I> with &[I] as the latter is a strict superset of the former.)
use std::marker::PhantomData;
type Input<'a,I> = &'a [I];
type Output<'a,I,O> = Option<(&'a [I], O)>;
struct Parser<I, O, F>
where
F: Fn(Input<'_,I>) -> Output<'_, I, O>,
{
parse: F,
_phantom: PhantomData<(I, O)>,
}
impl<I, O, F> Parser<I, O, F>
where
F: Fn(Input<'_, I>) -> Output<'_, I, O>,
{
fn new(parse: F) -> Self {
Self {
parse,
_phantom: PhantomData,
}
}
fn parse_it<'a>(&'a self, input: Input<'a, I>) -> Output<'a, I, O> {
(self.parse)(input)
}
}
fn main() {
let parser = Parser::new(|v: &[i32]| Some((v, v.iter().fold(0, |acc, x| acc + x))));
println!("{:?}", parser.parse_it(&[1, 2, 3]));
// ^ Some(([1, 2, 3], 6))
}
I'm writing a binding for a C library with the help of rust-bindgen for which the function signatures are generated automatically into a bindings.rs as:
#[repr(C)]
struct A {
//...
}
struct B {
//...
}
extern "C" {
pub fn foo(x: *mut A, y: *mut B);
//...
}
I'm not very happy with this signature of foo because I know that x is a pointer to a constant struct. Moreover, I want to apply this idea to improve this signature into something like
extern "C" {
pub fn foo(x: &'_ A, y: &'_ mut B);
}
But binding.rs has a bunch functions like foo and rewriting them by hand is a very time consuming task and I think that macros (or something else) should help. For example, there might exist one (or several) magic macro rewrite!
// hide
mod ffi {
include!("binding.rs"); // so bunch of functions: foo, bar
}
// re-exports
extern "C" {
rewrite!(foo); // should expand to: pub fn foo(x: &'_A, y: &'_ mut B)
rewrite!(bar);
}
I'm at a very early stage of this work. I don't even know if such a problem can be solved by a macro or anything else, so I'm looking for any entry point.
I've cross-posted this question to the Rust user forum.
A declarative macro can't accomplish this but a procedural macro might be able to. With proc_macro2, you can modify the token stream of a function declaration by placing your rewrite attribute on it, e.g.
extern "C" {
#[rustify]
pub fn foo(x: *mut A, y: *mut B);
}
And your rustify macro would substitute *mut Typename with Option<&mut Typename>.
I don't know how you'd change the mut borrow offhand without replacing the original declaration with *const.
The code below reads numbers, sums them, then prints the sum. I've tried few annotations, but it didn't work. I must be missing something. How could I make it work?
use std::io;
use std::io::Read;
fn main() {
let mut buff = String::new();
io::stdin().read_to_string(&mut buff).expect("read_to_string error");
let v: i32 = buff
.split_whitespace()
.filter_map(|w| w.parse().ok())
.sum();
println!("{:?}", v);
}
Error message from compiler:
type annotations needed
--> src\main.rs:9:10
|
9 | .filter_map(|w| w.parse().ok())
| ^^^^^^^^^^ cannot infer type for `B`
Let's look up the signature of filter_map to see, what the complain is about:
fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> where F: FnMut(Self::Item) -> Option<B>,
Okay, so Option<B> is the result, which means he cannot infer what w.parse().ok() will be.
Let's try to give him a hint
.filter_map(|w| w.parse::<i32>().ok())
Let's compile an see.... Hurray!
So, lesson learned: Look up the signature and try to figure out, which part the compiler cannot infer and try to specify it.
The quick fix is to say which type you are parsing into:
let v: i32 = buff
.split_whitespace()
.filter_map(|w| w.parse::<i32>().ok())
.sum();
The reason is that filter_map has a type variable B, which would need to be inferred from the closure that you pass to it (the closure returns Option<B>). However, parse() also has a type variable for the type you are parsing into, which also can often be inferred. But here the type-checker would have to infer each of these types from each other, which obviously can't be done. To break the cycle, you have to tell it somewhere what the concrete type is.
You also could have fixed it by annotating filter_map. It's not as nice because filter_map has two type parameters, but you can still let the second one be inferred by using an _:
let v: i32 = buff
.split_whitespace()
.filter_map::<i32, _>(|w| w.parse().ok())
.sum();
As the title states I am looking to return a closure from a function which has some initial, mutable state. In the following examples CowRow is a struct with a time field. It also has a String field, so is thus not copyable. Concretely, I would like a function that looks something like:
pub fn agg1() -> Box<Fn(&CowRow)> {
let res = 0;
Box::new(move |r| { res += r.time; })
}
Of course, this produces the error:
src/queries.rs:9:25: 9:38 error: cannot assign to captured outer variable in an `Fn` closure
src/queries.rs:9 Box::new(move |r| { res += r.time; })
^~~~~~~~~~~~~
src/queries.rs:9:14: 9:41 help: consider changing this closure to take self by mutable reference
src/queries.rs:9 Box::new(move |r| { res += r.time; })
^~~~~~~~
It is my understanding that Rust needs to know about the size of returned values and because closures borrow their stack frame from their environment we need to introduce the Box and move to get a size for the return and put the closure on the heap.
Is there some way to also put res on the heap in this closures environment? Or otherwise allow for this behaviour? Of course I have looked at: Cannot borrow captured outer variable in an `Fn` closure as mutable but this seems overly complicated and it's not clear to me how this would perform in the case of multiple threads running this function simultaneously.
Another technique I tried was to change the closure to take a mutable reference to an i32 which I can initialise outside of the agg function. Example:
pub fn agg0() -> Box<Fn(&CowRow, &mut i32)> {
Box::new(move |r, &mut acc| { acc += r.time; })
}
However, this produces the error:
src/queries.rs:4:35: 4:48 error: re-assignment of immutable variable `acc` [E0384]
src/queries.rs:4 Box::new(move |r, &mut acc| { acc += r.time; })
^~~~~~~~~~~~~
src/queries.rs:4:35: 4:48 help: run `rustc --explain E0384` to see a detailed explanation
src/queries.rs:4:28: 4:31 note: prior assignment occurs here
src/queries.rs:4 Box::new(move |r, &mut acc| { acc += r.time; })
This one is a total mystery to me.
You need to do two things here: make res mutable, and return an FnMut closure, not an Fn one:
pub struct CowRow {
time: u64,
}
pub fn agg1() -> Box<FnMut(&CowRow) -> u64> {
let mut res = 0;
Box::new(move |r| { res += r.time; res })
}
fn main() {
let mut c = agg1();
let moo = CowRow { time: 2 };
println!("{:?}", c(&moo));
println!("{:?}", c(&moo));
println!("{:?}", c(&moo));
}
The Fn trait forbids the implementor from changing itself when invoked. Since this closure is modifying its own state, this means it cannot be Fn [1]. Instead, you need to use FnMut which does allow mutation of the closure's captured environment.
[1]: Unless you involve interior mutability, of course.
DK. already said how to fix agg1, but I wanted to explain what's wrong with agg0, for completeness.
pub fn agg0() -> Box<Fn(&CowRow, &mut i32)> {
Box::new(move |r, &mut acc| { acc += r.time; })
}
We can infer from agg0's return type that the type of the closure's second parameter is &mut i32. &mut acc is a pattern that deconstructs the mutable reference, defining acc as an i32, initialized to a copy of the referenced value. You can't mutate it, because you didn't define acc to be mutable (you'd need to write &mut mut acc instead of &mut acc), but that's not what you want anyway, because then you'd be mutating a copy. What you want is to mutate the pointed-to integer, so you need to define your closure like this:
pub fn agg0() -> Box<Fn(&CowRow, &mut i32)> {
Box::new(move |r, acc| { *acc += r.time; })
}
Here, the type of acc is &mut i32, so in order to mutate the i32, we need to dereference the pointer first (this yields an lvalue that refers to the i32 behind the pointer; it's not a copy!).
I am working through this Rust tutorial, and I'm trying to solve this problem:
Implement a function, incrementMut that takes as input a vector of integers and modifies the values of the original list by incrementing each value by one.
This seems like a fairly simple problem, yes?
I have been trying to get a solution to compile for a while now, and I'm beginning to lose hope. This is what I have so far:
fn main() {
let mut p = vec![1i, 2i, 3i];
increment_mut(p);
for &x in p.iter() {
print!("{} ", x);
}
println!("");
}
fn increment_mut(mut x: Vec<int>) {
for &mut i in x.iter() {
i += 1;
}
}
This is what the compiler says when I try to compile:
Compiling tut2 v0.0.1 (file:///home/nate/git/rust/tut2)
/home/nate/git/rust/tut2/src/main.rs:5:12: 5:13 error: use of moved value: `p`
/home/nate/git/rust/tut2/src/main.rs:5 for &x in p.iter() {
^
/home/nate/git/rust/tut2/src/main.rs:3:16: 3:17 note: `p` moved here because it has type `collections::vec::Vec<int>`, which is non-copyable
/home/nate/git/rust/tut2/src/main.rs:3 increment_mut(p);
^
error: aborting due to previous error
Could not compile `tut2`.
To learn more, run the command again with --verbose.
I also tried a version with references:
fn main() {
let mut p = vec![1i, 2i, 3i];
increment_mut(&p);
for &x in p.iter() {
print!("{} ", x);
}
println!("");
}
fn increment_mut(x: &mut Vec<int>) {
for &mut i in x.iter() {
i += 1i;
}
}
And the error:
Compiling tut2 v0.0.1 (file:///home/nate/git/rust/tut2)
/home/nate/git/rust/tut2/src/main.rs:3:16: 3:18 error: cannot borrow immutable dereference of `&`-pointer as mutable
/home/nate/git/rust/tut2/src/main.rs:3 increment_mut(&p);
^~
error: aborting due to previous error
Could not compile `tut2`.
To learn more, run the command again with --verbose.
I feel like I'm missing some core idea about memory ownership in Rust, and it's making solving trivial problems like this very difficult, could someone shed some light on this?
There are a few mistakes in your code.
increment_mut(&p), given a p that is Vec<int>, would require the function increment_mut(&Vec<int>); &-references and &mut-references are completely distinct things syntactically, and if you want a &mut-reference you must write &mut p, not &p.
You need to understand patterns and how they operate; for &mut i in x.iter() will not do what you intend it to: what it will do is take the &int that each iteration of x.iter() produces, dereference it (the &), copying the value (because int satisfies Copy, if you tried it with a non-Copy type like String it would not compile), and place it in the mutable variable i (mut i). That is, it is equivalent to for i in x.iter() { let mut i = *i; … }. The effect of this is that i += 1 is actually just incrementing a local variable and has no effect on the vector. You can fix this by using iter_mut, which produces &mut int rather than &int, and changing the &mut i pattern to just i and the i += 1 to *i += 1, meaning “change the int inside the &mut int.
You can also switch from using &mut Vec<int> to using &mut [int] by calling .as_mut_slice() on your vector. This is a better practice; you should practically never need a reference to a vector as that is taking two levels of indirection where only one is needed. Ditto for &String—it’s exceedingly rare, you should in such cases work with &str.
So then:
fn main() {
let mut p = vec![1i, 2i, 3i];
increment_mut(p.as_mut_slice());
for &x in p.iter() {
print!("{} ", x);
}
println!("");
}
fn increment_mut(x: &mut [int]) {
for i in x.iter_mut() {
*i += 1;
}
}