Is there a shorter way of appending to a vector in a method call that takes self by value? - vector

I need to append Bar to Foo as vectors. This solution works for me:
trait AppendBar {
fn append_bar(self) -> Self;
}
impl AppendBar for Vec<String> {
fn append_bar(self) -> Vec<String> {
let mut v = self;
v.push("Bar".to_string());
v
}
}
fn main(){
let foo = vec![String::from("Foo")].append_bar();
println!("{:#?}", foo)
}
Can I do something like this:
impl AppendBar for Vec<String> {
fn append_bar(self) -> Vec<String> {
let mut v = self.push("Bar".to_string());
v
}
}
Or this:
impl AppendBar for Vec<String> {
fn append_bar(self) -> Vec<String> {
self.push("Bar".to_string())
}
}
Since I could not get it to compile with either of the last 2 attempts, I assume this is just how the language is, but I want to make sure I am not missing something to make it more simple.

There is no need to rebind self to v to achieve mutability. Just declare it as mut self:
fn append_bar(mut self) -> Vec<String> {
self.push("Bar".to_string());
self
}
Beyond that, there are no standard Vec methods for chaining modifications (consuming self and returning modified version), pretty much all methods modify the Vec in-place as &mut self.

Related

What is the most efficient way to return/move a Vec/Field in rust while also emptying it? [duplicate]

I have a struct with a field:
struct A {
field: SomeType,
}
Given a &mut A, how can I move the value of field and swap in a new value?
fn foo(a: &mut A) {
let mut my_local_var = a.field;
a.field = SomeType::new();
// ...
// do things with my_local_var
// some operations may modify the NEW field's value as well.
}
The end goal would be the equivalent of a get_and_set() operation. I'm not worried about concurrency in this case.
Use std::mem::swap().
fn foo(a: &mut A) {
let mut my_local_var = SomeType::new();
mem::swap(&mut a.field, &mut my_local_var);
}
Or std::mem::replace().
fn foo(a: &mut A) {
let mut my_local_var = mem::replace(&mut a.field, SomeType::new());
}
If your type implements Default, you can use std::mem::take:
#[derive(Default)]
struct SomeType;
fn foo(a: &mut A) {
let mut my_local_var = std::mem::take(&mut a.field);
}
If your field happens to be an Option, there's a specific method you can use — Option::take:
struct A {
field: Option<SomeType>,
}
fn foo(a: &mut A) {
let old = a.field.take();
// a.field is now None, old is whatever a.field used to be
}
The implementation of Option::take uses mem::take, just like the more generic answer above shows, but it is wrapped up nicely for you:
pub fn take(&mut self) -> Option<T> {
mem::take(self)
}
See also:
Temporarily move out of borrowed content
Change enum variant while moving the field to the new variant

How to implement a Future or Stream that polls an async fn?

I have a struct Test I want to implement std::future::Future that would poll function:
use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
struct Test;
impl Test {
async fn function(&mut self) {}
}
impl Future for Test {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match self.function() {
Poll::Pending => Poll::Pending,
Poll::Ready(_) => Poll::Ready(()),
}
}
}
That didn't work:
error[E0308]: mismatched types
--> src/lib.rs:17:13
|
10 | async fn function(&mut self) {}
| - the `Output` of this `async fn`'s expected opaque type
...
17 | Poll::Pending => Poll::Pending,
| ^^^^^^^^^^^^^ expected opaque type, found enum `Poll`
|
= note: expected opaque type `impl Future`
found enum `Poll<_>`
error[E0308]: mismatched types
--> src/lib.rs:18:13
|
10 | async fn function(&mut self) {}
| - the `Output` of this `async fn`'s expected opaque type
...
18 | Poll::Ready(_) => Poll::Ready(()),
| ^^^^^^^^^^^^^^ expected opaque type, found enum `Poll`
|
= note: expected opaque type `impl Future`
found enum `Poll<_>`
I understand that function must be called once, the returned Future must be stored somewhere in the struct, and then the saved future must be polled. I tried this:
struct Test(Option<Box<Pin<dyn Future<Output = ()>>>>);
impl Test {
async fn function(&mut self) {}
fn new() -> Self {
let mut s = Self(None);
s.0 = Some(Box::pin(s.function()));
s
}
}
That also didn't work:
error[E0277]: the size for values of type `(dyn Future<Output = ()> + 'static)` cannot be known at compilation time
--> src/lib.rs:7:13
|
7 | struct Test(Option<Box<Pin<dyn Future<Output = ()>>>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn Future<Output = ()> + 'static)`
After I call function() I have taken a &mut reference of Test, because of that I can't change the Test variable, and therefore can't store the returned Future inside the Test.
I did get an unsafe solution (inspired by this)
struct Test<'a>(Option<BoxFuture<'a, ()>>);
impl Test<'_> {
async fn function(&mut self) {
println!("I'm alive!");
}
fn new() -> Self {
let mut s = Self(None);
s.0 = Some(unsafe { &mut *(&mut s as *mut Self) }.function().boxed());
s
}
}
impl Future for Test<'_> {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.0.as_mut().unwrap().poll_unpin(cx)
}
}
I hope that there is another way.
Though there are times when you may want to do things similar to what you're trying to accomplish here, they are a rarity. So most people reading this, maybe even OP, may wish to restructure such that struct state and data used for a single async execution are different objects.
To answer your question, yes it is somewhat possible. Unless you want to absolutely resort to unsafe code you will need to use Mutex and Arc. All fields you wish to manipulate inside the async fn will have to be wrapped inside a Mutex and the function itself will accept an Arc<Self>.
I must stress, however, that this is not a beautiful solution and you probably don't want to do this. Depending on your specific case your solution may vary, but my guess of what OP is trying to accomplish while using Streams would be better solved by something similar to this gist that I wrote.
use std::{
future::Future,
pin::Pin,
sync::{Arc, Mutex},
};
struct Test {
state: Mutex<Option<Pin<Box<dyn Future<Output = ()>>>>>,
// if available use your async library's Mutex to `.await` locks on `buffer` instead
buffer: Mutex<Vec<u8>>,
}
impl Test {
async fn function(self: Arc<Self>) {
for i in 0..16u8 {
let data: Vec<u8> = vec![i]; // = fs::read(&format("file-{}.txt", i)).await.unwrap();
let mut buflock = self.buffer.lock().unwrap();
buflock.extend_from_slice(&data);
}
}
pub fn new() -> Arc<Self> {
let s = Arc::new(Self {
state: Default::default(),
buffer: Default::default(),
});
{
// start by trying to aquire a lock to the Mutex of the Box
let mut lock = s.state.lock().unwrap();
// create boxed future
let b = Box::pin(s.clone().function());
// insert value into the mutex
*lock = Some(b);
} // block causes the lock to be released
s
}
}
impl Future for Test {
type Output = ();
fn poll(
self: std::pin::Pin<&mut Self>,
ctx: &mut std::task::Context<'_>,
) -> std::task::Poll<<Self as std::future::Future>::Output> {
let mut lock = self.state.lock().unwrap();
let fut: &mut Pin<Box<dyn Future<Output = ()>>> = lock.as_mut().unwrap();
Future::poll(fut.as_mut(), ctx)
}
}
I'm not sure what you want to achieve and why, but I suspect that you're trying to implement Future for Test based on some ancient tutorial or misunderstanding and just overcomplicating things.
You don't have to implement Future manually. An async function
async fn function(...) {...}
is really just syntax sugar translated behind the scenes into something like
fn function(...) -> Future<()> {...}
All you have to do is to use the result of the function the same way as any future, e.g. use await on it or call block a reactor until it's finished. E.g. based on your first version, you can simply call:
let mut test = Test{};
test.function().await;
UPDATE1
Based on your descriptions I still think you're trying to overcomplicate this minimal working snippet without the need to manually implement Future for anything:
async fn asyncio() { println!("Doing async IO"); }
struct Test {
count: u32,
}
impl Test {
async fn function(&mut self) {
asyncio().await;
self.count += 1;
}
}
#[tokio::main]
async fn main() {
let mut test = Test{count: 0};
test.function().await;
println!("Count: {}", test.count);
}

Cannot use `impl Future` to store async function in a vector

I am trying to store async functions in a vector, but it seems like impl cannot be used in the vector type definition:
use std::future::Future;
fn main() {
let mut v: Vec<fn() -> impl Future<Output = ()>> = vec![];
v.push(haha);
}
async fn haha() {
println!("haha");
}
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
--> src/main.rs:4:28
|
4 | let mut v: Vec<fn() -> impl Future<Output = ()>> = vec![];
| ^^^^^^^^^^^^^^^^^^^^^^^^
How do I write the type inside the vector?
I found that there may be a workaround by using a type alias, so I changed the code:
use std::future::Future;
type Haha = impl Future<Output = ()>;
fn main() {
let mut v: Vec<fn() -> Haha> = vec![];
v.push(haha);
}
async fn haha() {
println!("haha");
}
This doesn't work either; this time the error occurs in the type alias:
error[E0658]: `impl Trait` in type aliases is unstable
--> src/main.rs:3:1
|
3 | type Haha = impl Future<Output = ()>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/63063
error[E0308]: mismatched types
--> src/main.rs:8:12
|
8 | v.push(haha);
| ^^^^ expected opaque type, found a different opaque type
|
= note: expected type `fn() -> Haha`
found type `fn() -> impl std::future::Future {haha}`
= note: distinct uses of `impl Trait` result in different opaque types
error: could not find defining uses
--> src/main.rs:3:1
|
3 | type Haha = impl Future<Output = ()>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
How do I fix it?
You cannot use the impl Trait this way. To be able to store different types that implement a trait into the same container you have to use dynamic dispatch, by storing something like Box<dyn Trait>.
In your particular case, you do not specify if you want to store the async functions themselves or the future generated by the async functions, the solution would be somewhat different.
To store just the futures, you write a container such as:
let mut v: Vec<Box<dyn Future<Output = ()>>> = vec![];
And then just call the function, box it and store it in the container:
v.push(Box::new(haha()));
If instead you want to store the async function itself, without calling it, you need a container with a double dyn:
let mut v2: Vec<Box<dyn Fn() -> Box<dyn Future<Output = ()>>>> = vec![];
Now, since your haha function does not implement this Fn trait you need an adaptor. A lambda function will do, but don't forget the double Box:
v2.push(Box::new(|| Box::new(haha())));
Unfortunately, with these solutions you will be able to create the vector, but not to .await for your futures. For that you need the futures to implement the Unpin marker. That guarantees to the compiler that the future will not move while it is running (if it did, the implementation would be totally unsafe). You could add the + Unpin requirement to the futures, but async fn are not Unpin so you could not fill the vector. The easiest way to fix it is to use this handy function from std:
pub fn into_pin(boxed: Box<T>) -> Pin<Box<T>>
for f in v2 {
f().into_pin().await;
}
Unfortunately, it is still unstable. Fortunately, there is a From impl that does exactly the same. So you can just write:
for f in v2 {
Pin::from(f()).await;
}
In your comment below you write this code to wait for the futures:
for f in v2 {
async { f().await }
}
Note that an async block itself will evaluate to another future, so here you are just wrapping each future into another future, but nobody is waiting for that one. Actually you'll get a warning about it:
warning: unused implementer of std::future::Future that must be used.
Remember that in order to properly wait for all the futures you will need an async runtime.
rodrigo's answer is correct, but I'd prefer to use Box::pin and bake the Pin type into the API of the collection. This makes using the Future trait object (or closure trait object producing a Future trait object) easier:
use std::{future::Future, pin::Pin};
type PinFutureObj<Output> = Pin<Box<dyn Future<Output = Output>>>;
async fn collection_of_pinned_future_trait_objects() {
let v: Vec<PinFutureObj<()>> = vec![
Box::pin(haha()),
Box::pin(hehe()),
Box::pin(haha()),
Box::pin(hehe()),
];
for f in v {
f.await
}
}
async fn collection_of_closure_trait_objects() {
let v: Vec<Box<dyn Fn() -> PinFutureObj<()>>> = vec![
Box::new(|| Box::pin(haha())),
Box::new(|| Box::pin(hehe())),
Box::new(|| Box::pin(haha())),
Box::new(|| Box::pin(hehe())),
];
for f in v {
f().await
}
}
async fn haha() {
println!("haha");
}
async fn hehe() {
println!("hehe");
}
I'd also start introducing type aliases for the longer types.
In fact, this type alias already exists in the futures crate as LocalBoxFuture and can be created via FutureExt::boxed_local. There's also BoxFuture produced by FutureExt::boxed which adds common trait bounds.
use futures::future::{FutureExt, LocalBoxFuture}; // 0.3.5
async fn collection_of_pinned_future_trait_objects() {
let v: Vec<LocalBoxFuture<'static, ()>> = vec![
haha().boxed_local(),
hehe().boxed_local(),
haha().boxed_local(),
hehe().boxed_local(),
];
for f in v {
f.await
}
}
async fn collection_of_closure_trait_objects() {
let v: Vec<Box<dyn Fn() -> LocalBoxFuture<'static, ()>>> = vec![
Box::new(|| haha().boxed_local()),
Box::new(|| hehe().boxed_local()),
Box::new(|| haha().boxed_local()),
Box::new(|| hehe().boxed_local()),
];
for f in v {
f().await
}
}
async fn haha() {
println!("haha");
}
async fn hehe() {
println!("hehe");
}
See also:
How can I put an async function into a map in Rust?
Why can impl trait not be used to return multiple / conditional types?

How can I send my Vec to a function taking an Iterator as a parameter?

I have an issue where I've got a function that takes in an Iterator of a specific struct type, and I want to send in my Vector that contains this same struct-type as a parameter to the function.
I do not understand what I am doing wrong. I have tried several different things:
Sending the vecName.iter() leaving me with this error: error[E0271]: type mismatch resolving <std::slice::Iter<'_, code_test_lib::gfx::AsteroidDrawData> as std::iter::Iterator>::Item == code_test_lib::gfx::AsteroidDrawData
Sending the vecName.into_iter() leaving me with this error: error[E0507]: cannot move out of borrowed content
Sending the &vecName.iter() giving me this error: error[E0277]: &std::slice::Iter<'_, code_test_lib::gfx::AsteroidDrawData> is not an iterator
Sending the &vecName.into_iter() giving me this: error[E0277]: &std::vec::IntoIter<code_test_lib::gfx::AsteroidDrawData> is not an iterator
I don't know how I can send the Vec to the function as an Iterator.
pub struct MyStruct {
pub dataA: f32,
pub dataB: f32,
}
struct MyProgram {
my_structs: Vec<MyStruct>,
}
pub trait BaseFunctions {
fn new() -> Self;
fn run(&mut self);
}
impl BaseFunctions for MyProgram {
fn new() -> Self {
//Create some data
let mut vec = Vec::new();
for x in 0..5 {
vec.push(MyStruct{
dataA: 1.0,
dataB: 1.0,
});
}
Self {
my_structs: vec,
}
}
fn run(&mut self) {
my_func(
self.my_structs.into_iter(),
);
}
}
pub fn my_func<Iter>(iter: Iter)
where
Iter: Iterator<Item = MyStruct>, {
for i in iter {
// Do something
}
}
fn main() {
let mut program = MyProgram::new();
program.run();
}
Your problem is that iter() generate an Iterator on reference not on the value. So you need to have a reference and a lifetime to your function. It's better to make a bound on IntoIterator that allow more generality.
pub fn my_func<'a, Iter>(iter: Iter)
where
Iter: IntoIterator<Item = &'a MyStruct>,
{
for i in iter {
// Do something
}
}
Call like this my_func(&self.my_structs); or my_func(self.my_structs.iter());

How do you replace the value of a mutable variable by taking ownership of it?

I am working with a LinkedList and I want to remove all elements which do not pass a test. However, I am running into the error cannot move out of borrowed content.
From what I understand, this is because I am working with &mut self, so I do not have the right to invalidate (i.e. move) one of the contained values even for a moment to construct a new list of its values.
In C++/Java, I would simply iterate the list and remove any elements which match a criteria. As there is no remove that I have yet found, I have interpreted it as an iterate, filter, and collect.
The goal is to avoid creating a temporary list, cloning values, and needing take self and return a "new" object. I have constructed an example which produces the same error. Playground.
use std::collections::LinkedList;
#[derive(Debug)]
struct Example {
list: LinkedList<i8>,
// Other stuff here
}
impl Example {
pub fn default() -> Example {
let mut list = LinkedList::new();
list.push_back(-5);
list.push_back(3);
list.push_back(-1);
list.push_back(6);
Example { list }
}
// Simmilar idea, but with creating a new list
pub fn get_positive(&self) -> LinkedList<i8> {
self.list.iter()
.filter(|&&x| x > 0)
.map(|x| x.clone())
.collect()
}
// Now, attempt to filter the elements without cloning anything
pub fn remove_negative(&mut self) {
self.list = self.list.into_iter()
.filter(|&x| x > 0)
.collect()
}
}
fn main() {
let mut e = Example::default();
println!("{:?}", e.get_positive());
println!("{:?}", e);
}
In my actual case, I cannot simply consume the wrapping object because it needs to be referenced from different places and contains other important values.
In my research, I found some unsafe code which leads me to question if a safe function could be constructed to perform this action in a similar way to std::mem::replace.
You can std::mem::swap your field with a temp, and then replace it with your modified list like this. The big downside is the creation of the new LinkedList. I don't know how expensive that is.
pub fn remove_negative(&mut self) {
let mut temp = LinkedList::new();
std::mem::swap(&mut temp, &mut self.list);
self.list = temp.into_iter()
.filter(|&x| x > 0)
.collect();
}
If the goal is not clone you may use a reference-counting pointer: the clone method on Rc increments the reference counter.
use std::collections::LinkedList;
use std::rc::Rc;
#[derive(Debug)]
struct Example {
list: LinkedList<Rc<i8>>,
// ...
}
impl Example {
pub fn default() -> Example {
let mut list = LinkedList::new();
list.push_back(Rc::new(-5));
list.push_back(Rc::new(3));
list.push_back(Rc::new(-1));
list.push_back(Rc::new(6));
Example { list }
}
// Simmilar idea, but with creating a new list
pub fn get_positive(&self) -> LinkedList<Rc<i8>> {
self.list.iter()
.filter(|&x| x.as_ref() > &0)
.map(|x| x.clone())
.collect()
}
// Now, attempt to filter the elements without cloning anything
pub fn remove_negative(&mut self) {
self.list = self.list.iter()
.filter(|&x| x.as_ref() > &0)
.map(|x| x.clone())
.collect()
}
}
fn main() {
let mut e = Example::default();
e.remove_negative();
println!("{:?}", e.get_positive());
println!("{:?}", e);
}

Resources