How to constraint quickcheck test argument to be non-empty in Rust - rust

I am trying to write a test which depends on non-empty vector of tuples as an argument but unsure of how to add such a constraint using quickcheck.
#[quickcheck]
fn graph_contains_vertex(vs: Vec<(u64, i64)>) {
// ...
let rand_index = rand::thread_rng().gen_range(0..vs.len());
let rand_vertex = vs.get(rand_index).unwrap().0;
// ...
}
What I am trying to do here is pick up an index from the vector passed as an argument and use first tuple value.
I ran a couple of tests and ended up with a use case where argument passed is [].

Apparently, we can handle invalid arguments right inside our tests like so:
#[quickcheck]
fn graph_contains_vertex(vs: Vec<(u64, i64)>) -> TestResult {
if vs.is_empty() {
return TestResult::discard();
}
// ..
let rand_index = rand::thread_rng().gen_range(0..vs.len());
let rand_vertex = vs.get(rand_index).unwrap().0;
// ...
TestResult::from_bool(g.contains(rand_vertex))
}
In this particular example, since I was depending on a non-empty vector argument, I could choose to discard the test results when received an empty vector using TestResult::discard().

Related

How do i split a string twice in rust?

i need split String "fooo:3333#baaar:22222"
Firstly by # secondary by :
and result must be <Vec<Vec<&str, i64>>>
for the first step (split by #) i came up with
.split('#').collect::<Vec<&str>>()
but I can't think of a solution for the second step
A Vec<&str, i64> is not a thing, so I assume you meant (&str, i64)
You can create that by splitting first, then mapping over the chunks.
let v = s
.split('#') // split first time
// "map" over the chunks and only take those where
// the conversion to i64 worked
.filter_map(|c| {
// split once returns an `Option<(&str, &str)>`
c.split_once(':')
// so we use `and_then` and return another `Option`
// when the conversion worked (`.ok()` converts the `Result` to an `Option`)
.and_then(|(l, r)| r.parse().ok().map(|r| (l, r)))
})
.collect::<Vec<(&str, i64)>>();
References:
https://doc.rust-lang.org/std/primitive.str.html#method.split
https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter_map
https://doc.rust-lang.org/core/primitive.str.html#method.split_once
https://doc.rust-lang.org/core/option/enum.Option.html#method.and_then
https://doc.rust-lang.org/std/primitive.str.html#method.parse
https://doc.rust-lang.org/std/result/enum.Result.html#method.ok
You can call a closure on each element of an iterator returned by the first split and split inside closure and push values to the vector.
let mut out = Vec::new();
s.split('#').for_each(|x| out.push(x.split(":").collect::<Vec<&str>>()));

Apparent unused variable in match statement

I am implementing a simple library system to keep track of my pdfs.
I have a Subject enum and a Entry struct defined as follows:
pub enum Subject {
Math,
Programming,
CompSci,
Language,
Misc,
None
}
pub struct Entry {
pub subject: Subject
}
I am trying to implement a function that will operate on a vector of Entry's and return a Vec<&Entry> whose entries match a given Subject.
I have a simple Library struct that is a wrapper around a Vec<Entry>:
pub struct Library {
pub entries: Vec<Entry>
}
In order to do so, I need to iterate through entries and filter only the elements whose .subject field correspond to the desired subject. To accomplish this I have created a function that will return a predicate function.
Here is the get_subject function:
impl Library {
pub fn get_subject(&self, subject: Subject) -> Vec<&Entry> {
let pred = subject_pred(subject);
self.entries.iter().filter(pred).collect::<Vec<&Entry>>()
}
}
which calls the function subject_pred to create the correct predicate function:
// Return a PREDICATE that returns true when
// the passed ENTRY matches the desired SUBJECT
fn subject_pred(subject_UNUSED: Subject) -> impl FnMut(&&Entry) -> bool {
|e: &&Entry| if matches!(&e.subject, subject_UNUSED) {
true
} else {
false
}
}
Here's the problem. This syntax compiles just fine but apparently the subject_UNUSED local variable in subject_pred is "unused". I am flabbergasted as my syntax clearly shows intent to match with the passed subject_UNUSED. When I test out this function on a vector of entries, the predicate always returns true (hence why I am receiving the "unused" warning) but I have literally no idea why.
If anyone could explain why the match statement is always matched, that would be greatly appreciated. I tried using a regular match statement but the same warning is popping up, and this is not the behavior that I am trying to code. If I don't include the subject_UNUSED in a traditional match statement, the compiler tells me that I have to cover the Math, Programming, CompSci, Language, Misc and None variants of my enum, which indicates to me that everything up until that point is good.
You cannot match against a variable. What you've done is equivalent to
matches!(&e.subject, some_subject)
That matches any Subject, just like a wildcard (_), except it also captures it in the some_subject variable (can be used in a guard like matches!(&e.subject, subject_UNUSED if subject_UNUSED == ...)). Neither the captured variable nor the parameter (which is shadowed by it) are used.
What you need to do is to #[derive(PartialEq)] then use ==:
if e.subject == subject_UNUSED { ... }
By the way, your code also has other problems: you don't move into the closure and you're taking owned entries but produce borrowed.

Rust function syntax question, example seem in nom

I'm looking at the nom crate for rust, which contains lots of functions to parse bytes/characters.
Many of the functions, such as tag(), seen below, process input that's provided not as a parameter to the function, but that appears instead in a second set of parentheses, following what I would call the parameters. If, in examples, one looks for a needle in a haystack, then the tag() function uses a parameter of its own, which is how one specifies the needle, but the haystack is specified separately, after the parameter parentheses, inside parentheses of its own (perhaps because it's a single value tuple?).
use nom::bytes::complete::tag;
fn parser(s: &str) -> IResult<&str, &str> {
tag("Hello")(s)
}
In the example above, tag()'s job is to test whether the input s starts with Hello. You can call parser, passing in "Hello everybody!, and the tag() function does indeed verify that the start of s is Hello. But how did (s) find its way into tag()?
Can someone explain this syntax to me, or show where to read about it. It works, and I can use it, but I don't understand what I'm looking at!
thanks
The return value of tag() is impl Fn(Input) -> IResult<Input, Input, Error>, i.e. the function returns another function. The first set of parentheses is for calling tag(); the second set is for calling the function it returns.
This allows you to store the "parser" returned by these functions in a variable and use it multiple times. Or, put differently, instead of the function definition in your question you could also write
let parser = tag("Hello");
and then call parser the same way you would call the function.
tag("Hello") just returns a function, which is then immediately invoked with the argument s, i.e. tag("Hello")(s). Here's a simple implementation example:
fn tag<'a>(needle: &'a str) -> impl Fn(&str) -> bool + 'a {
move |haystack: &str| haystack.starts_with(needle)
}
fn parser(s: &str) -> bool {
tag("Hello")(s)
}
fn main() {
println!("{}", parser("Hello everbody!")); // true
println!("{}", parser("Bye everybody!")); // false
}
playground

Assign return value when index check out of bounds

In pseudo-code, I'm trying the following:
for i in len(array):
try:
a = array[i-1]
except(out_of_bounds_error):
a = false
where array is just made up of booleans.
In the book (Chapter 9.2) it says you can check whether a function returns a result or not with something like:
let a: u32 = array[i-1]
which tells me a is indeed a bool. Without a Result type, how do I handle the inevitable (and expected) attempt to subtract with overflow error at runtime?
The error attempt to subtract with overflow occurs when computing i - 1 when i == 0. Array indices must be of type usize, which is an unsigned type, and unsigned types cannot represent negative numbers, which 0 - 1 would produce. In a debug build, the compiler generates code that raises this error, but in a release build, the compiler generates code that will simply compute the "wrong" value (in this case, this happens to be usize::max_value()).
You can avoid this error in both debug builds and release builds by performing a checked subtraction instead. checked_sub returns an Option: you'll get a Some if the subtraction succeeded or None if it failed. You can then use map_or on that Option to read the array only if the subtraction produced a valid index.
fn main() {
let a = vec![true; 10];
for i in 0..a.len() {
let b = i.checked_sub(1).map_or(false, |j| a[j]);
println!("b: {}", b);
}
}
Arrays (or rather, slices) also have a get method that returns an Option if the index is out of bounds, instead of panicking. If we were adding one to the index, instead of subtracting one, we could do this:
fn main() {
let a = vec![true; 10];
for i in 0..a.len() {
let b = i.checked_add(1).and_then(|j| a.get(j).cloned()).unwrap_or(false);
println!("b: {}", b);
}
}
This time, we're using and_then to chain an operation that produces an Option with another operation that also produces an Option, and we're using unwrap_or to get the Option's value or a default value if it's None.

What are Some and None?

I came across some output I don't understand using Vec::get. Here's the code:
fn main() {
let command = [('G', 'H'), ('H', '5')];
for i in 0..3 {
print!(" {} ", i);
println!("{:?}", command.get(i));
}
}
the output is
0 Some(('G', 'H'))
1 Some(('H', '5'))
2 None
I've dabbled in Haskell before, and by that I mean looked at a tutorial site for 10 minutes and ran back to C++, but I remember reading something about Some and None for Haskell. I was surprised to see this here in Rust. Could someone explain why .get() returns Some or None?
The signature of get (for slices, not Vec, since you're using an array/slice) is
fn get(&self, index: usize) -> Option<&T>
That is, it returns an Option, which is an enum defined like
pub enum Option<T> {
None,
Some(T),
}
None and Some are the variants of the enum, that is, a value with type Option<T> can either be a None, or it can be a Some containing a value of type T. You can create the Option enum using the variants as well:
let foo = Some(42);
let bar = None;
This is the same as the core data Maybe a = Nothing | Just a type in Haskell; both represent an optional value, it's either there (Some/Just), or it's not (None/Nothing).
These types are often used to represent failure when there's only one possibility for why something failed, for example, .get uses Option to give type-safe bounds-checked array access: it returns None (i.e. no data) when the index is out of bounds, otherwise it returns a Some containing the requested pointer.
See also:
Why don't Option's Some and None variants need to be qualified?
What is the difference between Some and Option in Rust?
Think of Some and None as the canonical "safe" way of working around the fact that the Rust language does not support "safe" use of NULL pointers. Since the length of your Vec is 3, and you have only specified two pairs, the third pair is effectively NULL; instead of returning NULL, it returns None.
Rust provides safety guarantees by forcing us at compile-time, via Some / None, to always deal with the possibility of None being returned.
command is not a vector (type Vec<T>), it is a fixed-size array (type [(char, char); 2] in your case), and arrays are automatically borrowed into slices (views into arrays), hence you can use all methods defined on slices, including get:
Returns the element of a slice at the given index, or None if the index is out of bounds.
The behavior is pretty obvious: when given index is valid, it returns Some with the element under that index, otherwise it returns None.
There is another way to access elements in a slice - the indexing operator, which should be familiar to you:
let nums = [1, 2, 3];
let x = nums[1];
It returns the element of the slice directly, but it will fail the current task if the index is out of bounds:
fn main() {
let x = [1, 2];
for i in 0..3 {
println!("{}", x[i]);
}
}
This program fails:
% ./main2
1
2
task '<main>' failed at 'index out of bounds: the len is 2 but the index is 2', main2.rs:4
The get() method is needed for convenience; it saves you from checking in advance if the given index is valid.
If you don't know what Some and None really are and why they are needed in general, you should read the official tutorial, it explains it because it is very basic concept.
Option enum has 2 variants.
1- None is used to indicate failure or no value
2- Some which is tuple-struct that wraps the value
If you need to write this structure in OOB, for example in typescript, you would write like this. This would make it easier to visualize the situation
Define Option interface as derived class
interface Option<T = any> {
// pass all the methods here
// unwrap is used to access the wrapped value
unwrap(): T;
}
write Some class which inherits from Option
Some class returns a value
class Some<T> implements Option<T> {
private value: T;
constructor(v: T) {
this.value = v;
}
unwrap(): T {
return this.value
}}
Write None class which also inherits from Option
None class returns null
class None<T> implements Option<T> {
// you do not need constructor here
unwrap(): T {
return null as T;
}
}
The other answers discussing the return type for get() being option enum are accurate, but I think what is helpful is how to remove the some from the prints. To do that a quick way is to just call the unwrap on the option, although this is not production recommended. For a discussion on option take a look at the rust book here.
Updated with unwrap code in playground (below)
fn main() {
let command = [('G', 'H'), ('H', '5')];
for i in 0..3 {
print!(" {} ", i);
println!("{:?}", command.get(i).unwrap());
}
}

Resources