I am trying to learn more about ownership. Here is some code that doesn't work because collect doesn't let you get a &mut String:
fn search(word: &str, data: &mut Vec<String>) {
data = data
.iter()
.filter(|x| x.contains(word))
.collect::<&mut Vec<String>>();
}
I think I could just return a cloned version, but is this the only/preferred way to do it?
No, it is not possible. For this to be possible, collect would have to return a reference to something it created, and that's not possible.
You are looking for Vec::retain:
fn search(word: &str, data: &mut Vec<String>) {
data.retain(|x| x.contains(word));
}
If you didn't want to mutate the passed-in data, you would indeed need to return a new Vec:
fn search<'a>(word: &str, data: &'a [String]) -> Vec<&'a String> {
data.iter().filter(|x| x.contains(word)).collect()
}
See also:
Is there any way to return a reference to a variable created in a function?
Why is it discouraged to accept a reference to a String (&String), Vec (&Vec) or Box (&Box) as a function argument?
Related
The title should have already suggest you I have noticed How can I put an async function into a map in Rust? and I have failed to proceed my work. Here is my sample code based on above link:
extern crate async_std;
use async_std::task;
use std::future::Future;
use std::pin::Pin;
use std::boxed::Box;
type VarIn = &String;
type VarOut = String;
type FnType = Box< dyn Fn(VarIn) -> Pin<Box<dyn Future<Output=VarOut>>> >;
async fn test(v: FnType) {
println!("{}", v("hi".to_string()).await)
}
async fn var(s: &String) -> String {
format!("var:{}", s)
}
fn main() {
task::block_on(test(Box::new(|s| Box::pin(var(s)))));
}
If VarIn is replaced by String instead of &String then everything is fine. However, my use case needs me to pass a reference instead to fulfill my usage (I use it in an infinite loop, so I can't pass the ownership to this function). What should I do to successfully pass the reference to async function, or there is some design to circumvent this?
You have to specify in the type definitions that are used in the function test what the lifetime of the reference is and how it relates to the Future.
VarIn<'a> = &'a String;
VarOut = String;
FnType<'a> = Box<dyn Fn(VarIn<'a>) -> Pin<Box<dyn Future<Output=VarOut> + 'a>>>;
This won't ultimately work, because the String created in test will be dropped at the bottom of the function, while the &String will be returned with the Future. You can use an &str and get this example to work, and that is what I suggest.
VarIn<'a> = &'a str
VarOut = String
FnType<'a> = Box<dyn Fn(VarIn<'a>) -> Pin<Box<dyn Future<Output=VarOut> + 'a>>>;
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d86d8b57b556c3d4c4e0282f890a2228
Let's say I have a &mut std::collections::HashMap, and I want to turn all the keys into uppercase. The following code does the trick:
use std::collections::HashMap;
fn keys_to_upper<T>(map: &mut HashMap<String, T>) {
let mut tmp = Vec::with_capacity(map.len());
for (key, val) in map.drain() {
tmp.push((key.to_ascii_uppercase(), val));
}
for (key, val) in tmp {
map.insert(key, val);
}
}
Unfortunately, I don't have a HashMap but a &mut serde_json::Map, and I want to turn all the keys into uppercase. There is no .drain() method. I could use .into_iter() instead, but that would only give me mutable references to the keys and values. To insert them into the map again I would have to clone them, which would hurt performance.
Is there some way here to get around the absense of the .drain() method?
A nice tool in your Rust programmer toolbox: std::mem::take.
This lets you change a &mut T to a T if the type implements default (if it doesn't, but the type still has a dummy/cheap value you can use, then std::mem::replace is your function of choice).
Applied to your current use-case this gives:
use serde_json::{Map, Value};
fn keys_to_upper<T>(map: &mut Map<String, Value>) {
*map = std::mem::take(map)
.into_iter()
.map(|(k, v)| (k.to_ascii_uppercase(), v))
.collect();
}
I'm filling a vector in parallel, but for this generalized question, I've only found hints and no answers.
The code below works, but I want to switch to Rng::fill instead of iterating over each chunk. It might not be possible to have multiple mutable slices inside a single Vec; I'm not sure.
extern crate rayon;
extern crate rand;
extern crate rand_xoshiro;
use rand::{Rng, SeedableRng};
use rand_xoshiro::Xoshiro256StarStar;
use rayon::prelude::*;
use std::{iter, env};
use std::sync::{Arc, Mutex};
// i16 because I was filling up my RAM for large tests...
fn gen_rand_vec(data: &mut [i16]) {
let num_threads = rayon::current_num_threads();
let mut rng = rand::thread_rng();
let mut prng = Xoshiro256StarStar::from_rng(&mut rng).unwrap();
// lazy iterator of fast, unique RNGs
// Arc and Mutex are just so it can be accessed from multiple threads
let rng_it = Arc::new(Mutex::new(iter::repeat(()).map(|()| {
let new_prng = prng.clone();
prng.jump();
new_prng
})));
// generates random numbers for each chunk in parallel
// par_chunks_mut is parallel version of chunks_mut
data.par_chunks_mut(data.len() / num_threads).for_each(|chunk| {
// I used extra braces because it might be required to unlock Mutex.
// Not sure.
let mut prng = { rng_it.lock().unwrap().next().unwrap() };
for i in chunk.iter_mut() {
*i = prng.gen_range(-1024, 1024);
}
});
}
It turns out that a ChunksMut iterator gives slices. I'm not sure how to glean that from the documentation. I figured it out by reading the source:
#[derive(Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct ChunksMut<'a, T:'a> {
v: &'a mut [T],
chunk_size: usize
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Iterator for ChunksMut<'a, T> {
type Item = &'a mut [T];
#[inline]
fn next(&mut self) -> Option<&'a mut [T]> {
if self.v.is_empty() {
None
} else {
let sz = cmp::min(self.v.len(), self.chunk_size);
let tmp = mem::replace(&mut self.v, &mut []);
let (head, tail) = tmp.split_at_mut(sz);
self.v = tail;
Some(head)
}
}
I guess it's just experience; to others it must be obvious that an iterator of type ChunksMut<T> from Vec<T> returns objects of type [T]. That makes sense now. It just wasn't very clear with the intermediate struct.
pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<T>
// ...
impl<'a, T> Iterator for ChunksMut<'a, T>
Reading this, it looked like the iterator returned objects of type T, the same as Vec<T>.iter(), which wouldn't make sense.
I have a cache-like structure which internally uses a HashMap:
impl Cache {
fn insert(&mut self, k: u32, v: String) {
self.map.insert(k, v);
}
fn borrow(&self, k: u32) -> Option<&String> {
self.map.get(&k)
}
}
Playground with external mutability
Now I need internal mutability. Since HashMap does not implement Copy, my guess is that RefCell is the path to follow. Writing the insert method is straight forward but I encountered problems with the borrow-function. I could return a Ref<String>, but since I'd like to cache the result, I wrote a small Ref-wrapper:
struct CacheRef<'a> {
borrow: Ref<'a, HashMap<u32, String>>,
value: &'a String,
}
This won't work since value references borrow, so the struct can't be constructed. I know that the reference is always valid: The map can't be mutated, because Ref locks the map. Is it safe to use a raw pointer instead of a reference?
struct CacheRef<'a> {
borrow: Ref<'a, HashMap<u32, String>>,
value: *const String,
}
Am I overlooking something here? Are there better (or faster) options? I'm trying to avoid RefCell due to the runtime overhead.
Playground with internal mutability
I'll complement #Shepmaster's safe but not quite as efficient answer with the unsafe version. For this, we'll pack some unsafe code in a utility function.
fn map_option<'a, T, F, U>(r: Ref<'a, T>, f: F) -> Option<Ref<'a, U>>
where
F: FnOnce(&'a T) -> Option<&'a U>
{
let stolen = r.deref() as *const T;
let ur = f(unsafe { &*stolen }).map(|sr| sr as *const U);
match ur {
Some(u) => Some(Ref::map(r, |_| unsafe { &*u })),
None => None
}
}
I'm pretty sure this code is correct. Although the compiler is rather unhappy with the lifetimes, they work out. We just have to inject some raw pointers to make the compiler shut up.
With this, the implementation of borrow becomes trivial:
fn borrow<'a>(&'a self, k: u32) -> Option<Ref<'a, String>> {
map_option(self.map.borrow(), |m| m.get(&k))
}
Updated playground link
The utility function only works for Option<&T>. Other containers (such as Result) would require their own modified copy, or else GATs or HKTs to implement generically.
I'm going to ignore your direct question in favor of a definitely safe alternative:
impl Cache {
fn insert(&self, k: u32, v: String) {
self.map.borrow_mut().insert(k, v);
}
fn borrow<'a>(&'a self, k: u32) -> Option<Ref<'a, String>> {
let borrow = self.map.borrow();
if borrow.contains_key(&k) {
Some(Ref::map(borrow, |hm| {
hm.get(&k).unwrap()
}))
} else {
None
}
}
}
Ref::map allows you to take a Ref<'a, T> and convert it into a Ref<'a, U>. The ugly part of this solution is that we have to lookup in the hashmap twice because I can't figure out how to make the ideal solution work:
Ref::map(borrow, |hm| {
hm.get(&k) // Returns an `Option`, not a `&...`
})
This might require Generic Associated Types (GATs) and even then the return type might be a Ref<Option<T>>.
As mentioned by Shepmaster, it is better to avoid unsafe when possible.
There are multiple possibilities:
Ref::map, with double look-up (as illustrated by Shepmaster's answer),
Ref::map with sentinel value,
Cloning the return value.
Personally, I'd consider the latter first. Store Rc<String> into your map and your method can easily return a Option<Rc<String>> which completely sidesteps the issues:
fn get(&self, k: u32) -> Option<Rc<String>> {
self.map.borrow().get(&k).cloned()
}
As a bonus, your cache is not "locked" any longer while you use the result.
Or, alternatively, you can work-around the fact that Ref::map does not like Option by using a sentinel value:
fn borrow<'a>(&'a self, k: u32) -> Ref<'a, str> {
let borrow = self.map.borrow();
Ref::map(borrow, |map| map.get(&k).map(|s| &s[..]).unwrap_or(""))
}
I'm having a lot of fun playing around with Rust having been a C# programmer for a long time but I have a question around reflection. Maybe I don't need reflection in this case but given that Rust is strongly typed I suspect I do (I would definitely need it in good ol' C#, bless its cotton socks).
I have this situation:
use std::collections::HashMap;
fn invoke_an_unknown_function(
hashmap: HashMap<String, String>,
// Something to denote a function I know nothing about goes here
) {
// For each key in the hash map, assign the value
// to the parameter argument whose name is the key
// and then invoke the function
}
How would I do that? I'm guessing I need to pass in some sort of MethodInfo as the second argument to the function and then poke around with that to get the arguments whose name is the key in the hash map and assign the values but I had a look around for the reflection API and found the following pre-Rust 1.0 documentation:
Module std::reflect
Module std::repr
[rust-dev] Reflection system
None of these give me enough to go on to get started. How would I implement the function I describe above?
Traits are the expected way to implement a fair amount of what reflection is (ab)used for elsewhere.
trait SomeInterface {
fn exposed1(&self, a: &str) -> bool;
fn exposed2(&self, b: i32) -> i32;
}
struct Implementation1 {
value: i32,
has_foo: bool,
}
impl SomeInterface for Implementation1 {
fn exposed1(&self, _a: &str) -> bool {
self.has_foo
}
fn exposed2(&self, b: i32) -> i32 {
self.value * b
}
}
fn test_interface(obj: &dyn SomeInterface) {
println!("{}", obj.exposed2(3));
}
fn main() {
let impl1 = Implementation1 {
value: 1,
has_foo: false,
};
test_interface(&impl1);
}