What is the best way to fill a slice from an iterator in Rust? [duplicate] - optimization

This question already has answers here:
How do I collect into an array?
(10 answers)
Closed 5 years ago.
I'm implementing FromIterator for [MyStruct;4] where MyStruct is a small Copy struct. My current implementation is
fn from_iter<I: IntoIterator<Item=MyStruct>>(iter: I) -> Self {
let mut retval = [Default::default();4];
for (ret, src) in retval.iter_mut().zip(iter) {
*ret = src;
}
retval
}
This works just fine, however I'm not sure that the for loop is as idiomatic as it could be. Is there perhaps a method like Slice::fill(iter) that could accomplish this more cleanly (and perhaps more efficiently)?

Loops are OK and they generally optimize very well.
Another solution may be to collect() into an ArrayVec. It avoids having to fill the array with a default value first.

Related

Why does indexing need to be referenced? [duplicate]

This question already has answers here:
What is the return type of the indexing operation?
(2 answers)
Closed 2 years ago.
I'm currently learning Rust coming from JavaScript.
My problem is the following:
fn main() {
let name = String::from("Tom");
let sliced = name[..2];
println!("{}, {}", name, sliced);
}
This doesn't work. Saying "doesn't have a size known at compile-time".
To fix this I need to add & the referencing operator.
fn main() {
let name = String::from("Tom");
let sliced = &name[..2];
println!("{}, {}", name, sliced);
}
I know I need to add & before name and & is the referencing operator. But I just don't know why I actually need to do that?
By referencing a variable the reference refers to variable name but does not own it. The original value will not get dropped if my reference gets out of scope. Does that mean that the variable gets out of scope if i do name[...] and the variable gets dropped and because of that i need to create a reference to it to prevent that?
Could somebody explain me that?
I know I need to add & before name and & is the referencing operator. But I just don't know why I actually need to do that.
I understand where the confusion come from, because when you look at index() it returns &Self::Output. So it already returns a reference, what's going on?
It's because the indexing operator is syntactic sugar and uses the Index trait. However, while it uses index() which does return a reference, that is not how it is desugared.
In short x[i] is not translated into x.index(i), but actually to *x.index(i), so the reference is immediately dereferenced. That's how you end up with a str instead of a &str.
let foo = "foo bar"[..3]; // str
// same as
let foo = *"foo bar".index(..3); // str
That's why you need to add the & to get it "back" to a reference.
let foo = &"foo bar"[..3]; // &str
// same as
let foo = &*"foo bar".index(..3); // &str
Alternatively, if you call index() directly, then it isn't implicitly dereferenced of course.
use std::ops::Index;
let foo = "foo bar".index(..3); // &str
Trait std::ops::Index - Rust Documentation:
container[index] is actually syntactic sugar for *container.index(index)
The same applies to IndexMut.

What patterns exist for mocking a single function while testing? [duplicate]

This question already has answers here:
How to mock specific methods but not all of them in Rust?
(2 answers)
How to mock external dependencies in tests? [duplicate]
(1 answer)
How can I test stdin and stdout?
(1 answer)
Is there a way of detecting whether code is being called from tests in Rust?
(1 answer)
What is the proper way to use the `cfg!` macro to choose between multiple implementations?
(1 answer)
Closed 3 years ago.
I have a function generates a salted hash digest for some data. For the salt, it uses a random u32 value. It looks something like this:
use rand::RngCore;
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;
fn hash(msg: &str) -> String {
let salt = rand::thread_rng().next_u32();
let mut s = DefaultHasher::new();
s.write_u32(salt);
s.write(msg.as_bytes());
format!("{:x}{:x}", &salt, s.finish())
}
In a test, I'd like to validate that it produces expected values, given a known salt and string. How do I mock (swizzle?) rand::thread_rng().next_u32() in the test to generate a specific value? In other words, what could replace the comment in this example to make the test pass?
mod tests {
#[test]
fn test_hashes() {
// XXX How to mock ThreadRng::next_u32() to return 3892864592?
assert_eq!(hash("foo"), "e80866501cdda8af09a0a656");
}
}
Some approaches I've looked at:
I'm aware that the ThreadRng returned by rand::thread_rng() implements RngCore, so in theory I could set a variable somewhere to store a reference to a RngCore, and implement my own mocked variant to set during testing. I've taken this sort of approach in Go and Java, but I couldn't get the Rust type checker to allow it.
I looked at the list of mock frameworks, such as MockAll, but they appear to be designed to mock a struct or trait to pass to a method, and this code doesn't pass one, and I wouldn't necessarily want users of the library to be able to pass in a RngCore.
Use the #[cfg(test)] macro to call a different function specified in the tests module, then have that function read the value to return from elsewhere. This I got to work, but had to use an unsafe mutable static variable to set the value for the mocked method to find, which seems gross. Is there a better way?
As a reference, I'll post an answer using the #[cfg(test)] + unsafe mutable static variable technique, but hope there's a more straightforward way to do this sort of thing.
In the test module, use lazy-static to add a static variable with a Mutex for thread safety, create a function like next_u32() to return its value, and have tests set the static variable to a known value. It should fall back on returning a properly random number if it's not set, so here I've made it Vec<u32> so it can tell:
mod tests {
use super::*;
use lazy_static::lazy_static;
use std::sync::Mutex;
lazy_static! {
static ref MOCK_SALT: Mutex<Vec<u32>> = Mutex::new(vec![]);
}
// Replaces random salt generation when testing.
pub fn mock_salt() -> u32 {
let mut sd = MOCK_SALT.lock().unwrap();
if sd.is_empty() {
rand::thread_rng().next_u32()
} else {
let ret = sd[0];
sd.clear();
ret
}
}
#[test]
fn test_hashes() {
MOCK_SALT.lock().unwrap().push(3892864592);
assert_eq!(hash("foo"), "e80866501cdda8af09a0a656");
}
}
Then modify hash() to call tests::mock_salt() instead of rand::thread_rng().next_u32() when testing (the first three lines of the function body are new):
fn hash(msg: &str) -> String {
#[cfg(test)]
let salt = tests::mock_salt();
#[cfg(not(test))]
let salt = rand::thread_rng().next_u32();
let mut s = DefaultHasher::new();
s.write_u32(salt);
s.write(msg.as_bytes());
format!("{:x}{:x}", &salt, s.finish())
}
Then use of the macros allows Rust to determine, at compile time, which function to call, so there's no loss of efficiency in non-test builds. It does mean that there's some knowledge of the tests module in the source code, but it's not included in the binary, so should be relatively safe. I suppose there could be a custom derive macro to automate this somehow. Something like:
#[mock(rand::thread_rng().next_u32())]
let salt = rand::thread_rng().next_u32();
Would auto-generate the mocked method in the tests module (or elsewhere?), slot it in here, and provide functions for the tests to set the value --- only when testing, of course. Seems like a lot, though.
Playground.

rayon::str::Lines<'_'> is not an iterator [duplicate]

This question already has answers here:
How to satisfy the Iterator trait bound in order to use Rayon here?
(1 answer)
Is there a way to directly consume a Rayon chain without collecting it first?
(1 answer)
Closed 3 years ago.
I'm trying process a file line by line in Rust and parallelise this using Rayon. It complains of the following
rayon::str::Lines<'_>` is not an iterator
= help: the trait `std::iter::Iterator` is not implemented for
= note: required by `std::iter::IntoIterator::into_iter`
This is what the code looks like so far
use rayon::prelude::*;
use std::fs;
fn main() {
let file_content = match fs::read_to_string("input.txt") {
Ok(s) => s,
Err(e) => {
eprintln!("Error: {}", e);
std::process::exit(1);
}
};
file_content = 5;
for line in file_content.par_lines() {
println!("{}", line);
}
std::process::exit(0);
}
Am I missing a trait definition? How could I fix this error?
You can't use parallel iterators with the (non-parallel) for loop.
Instead, use .for_each(|| …) callback on the parallel iterator.
Alternatively, first call .collect::<Vec<_>>(), and then non-parallel for.
For more advanced cases you can also send results to a channel in parallel, and then use non-parallel for to read from the channel.

How to convert valueForKeyPath in swift

My old function in objective c is
+ (NSUInteger)getNumberOfDistinctUsers:(NSArray *)users {
NSArray* usersAfterPredicate = [users valueForKeyPath:#"#distinctUnionOfObjects.userName"];
return [usersAfterPredicate count]; }
How do I convert this in swift, I was trying to something like this but its crashing "Could not cast value of type 'Swift.Array'to 'Swift.AnyObject'"
static func getNumberOfDistinctUsers(users: [ICEPKReferenceDataUser]) -> Int {
var retval : Int = 0
if let usersAfterPredicate = (users as! AnyObject).valueForKeyPath("#distinctUnionOfObjects.userName") {
retval = usersAfterPredicate.count
}
return retval
}
Can I solve this problem using filter, map or Reduce? I am just trying to find out distint users in users array using the property username.
Edit* brute force way
static func getNumberOfDistinctUsers(users: [ICEPKReferenceDataUser]) -> Int {
var retvalSet : Set<String> = []
for user in users {
retvalSet.insert(user.userName)
}
return retvalSet.count
}
As you suspect, you can simplify the code with a simple map:
static func getNumberOfDistinctUsers(users: [ICEPKReferenceDataUser]) -> Int {
return Set(users.lazy.map{$0.userName}).count
}
This uses the fact that you can initialize a Set using any other sequence.
I added lazy in there to avoid creating an extra copy of the array. It'll work with or without, but I expect it to be much more memory efficient this way. Array.map creates another Array. array.lazy.map return a lazy collection that computes values as requested.
That said, I don't know that my approach is dramatically better than your "brute-force" way. It's not obvious which is easer to read or maintain. I have a fondness for the map approach, but it can be a tradeoff (I had to know to add lazy for instance, or I could have allocated significant memory if this were a large array). Your code makes it very clear what's going on, so I don't think there's any problem that has to be solved there.
If you really wanted to use KVC, you'd need to convert your array to an NSArray, not an AnyObject, but I suspect that the above code is much faster, and is clearer and simpler, too, IMO.

Passing and recieving multi-dimensional primitive (int) arrays in objective-c

I have two objective c methods. One needs to return an int[][] and the other which needs to take int[][] as a parameter. I was originally using an NSMutableArray with NSMutableArrays as values however I was told to redo it like this in order to be compatible with some current code. I can't figure out how to make this work. I'm not sure I'm even googling the right thing. Anyway here is what I have now.
+(int [][consantValue]) getCoefficients
{
int coefficiennts [constantValue2][constantValue1] = { {0,1,2}, {3,4,5}, {6,7,8} };
return coefficients;
}
At the return statement I get the Error "Array initilizer must be an initializer list'
I also have to take the int[][] and rebuild it into an NSMutableArray of NSMutableArrays in another method but I'm hoping if someone can give me a hint on the first part I can work the second part out myself although if anyone has any advice on that I would appreciate it as well. Thanks.
The easy way to do this for fixed size array(s) is to use a struct for storage:
typedef struct {
int at[constantValue2][constantValue1];
} t_mon_coefficients;
And then you'd declare the method which returns by value:
+ (t_mon_coefficients)coefficients;
And passes by value as a parameter:
- (void)setCoefficients:(const t_mon_coefficients)pCoefficients;
If the struct is large, you should pass by reference:
// you'd use this like:
// t_mon_coefficients coef;
// [SomeClass getCoefficients:&coef];
+ (void)getCoefficients:(t_mon_coefficients* const)pOutCoefficients;
- (void)setCoefficients:(const t_mon_coefficients*)pCoefficients;
But there are multiple ways one could accomplish this.