This page in the guide for rocket has a piece of code as follows:
use rocket::form::Form;
#[derive(FromForm)]
struct Task<'r> {
complete: bool,
r#type: &'r str,
}
#[post("/todo", data = "<task>")]
fn new(task: Form<Task<'_>>) { /* .. */ }
What is the r# in the struct Task?
I know what a raw string literal is in Rust, which begins with r and is immediately bracketed by an arbitrary number of #. It seems however in the above snippet of code there is no closing #.
It allows you to escape the reserved word type and use it as a field of the struct. You can find more about 'raw identifiers' here.
Related
I'm trying to define a custom type of char that only accepts values from A-Z. Right now i'm just using a plain char in my type:
struct Rotor {
cipher: &'static str,
notch: &'static [char],
position: char, // Only valid values are A-Z
}
And here's a method that is invoked periodically on this struct
fn rotate(&mut self) {
match self.position /* E0004 on this line */ {
'A'..='Y' => self.position = (self.position as u8 + 1) as char,
'Z' => self.position = 'A',
}
}
the match statement in my rotate method is giving me compiler error E0004: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
If I could have a custom char type that only had values A-Z possible that would eliminate this error. I've considered using the following pattern: const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ"; but I can't figure out how to get that to work with the struct definition
I know that if I just added a catch-all _ arm to this match statement it wouldn't be the end of the world but I would much prefer to not have to do that
Rust does not support ranged integers (at least currently) and thus you cannot define your own character type and have the compiler enforce exhaustiveness with it. You have to use a wildcard. By the way, you can use the smaller and more efficient u8 if you only need A-Z.
You can use a newtype wrapper and have the constructor enforcing the validity of the value. This will not help with match, but will help to prevent bugs.
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.
This extremely simple Rust program:
fn main() {
let c = "hello";
println!(c);
}
throws the following compile-time error:
error: expected a literal
--> src/main.rs:3:14
|
3 | println!(c);
| ^
In previous versions of Rust, the error said:
error: format argument must be a string literal.
println!(c);
^
Replacing the program with:
fn main() {
println!("Hello");
}
Works fine.
The meaning of this error isn't clear to me and a Google search hasn't really shed light on it. Why does passing c to the println! macro cause a compile time error? This seems like quite unusual behaviour.
This should work:
fn main() {
let c = "hello";
println!("{}", c);
}
The string "{}" is a template where {} will be replaced by the next argument passed to println!.
TL;DR If you don't care why and just want to fix it, see the sibling answer.
The reason that
fn main() {
let c = "hello";
println!(c);
}
Cannot work is because the println! macro looks at the string at compile time and verifies that the arguments and argument specifiers match in amount and type (this is a very good thing!). At this point in time, during macro evaluation, it's not possible to tell that c came from a literal or a function or what have you.
Here's an example of what the macro expands out to:
let c = "hello";
match (&c,) {
(__arg0,) => {
#[inline]
#[allow(dead_code)]
static __STATIC_FMTSTR: &'static [&'static str] = &[""];
::std::io::stdio::println_args(&::std::fmt::Arguments::new(
__STATIC_FMTSTR,
&[::std::fmt::argument(::std::fmt::Show::fmt, __arg0)]
))
}
};
I don't think that it's actually impossible for the compiler to figure this out, but it would probably take a lot of work with potentially little gain. Macros operate on portions of the AST and the AST only has type information. To work in this case, the AST would have to include the source of the identifier and enough information to determine it's acceptable to be used as a format string. In addition, it might interact poorly with type inference - you'd want to know the type before it's been picked yet!
The error message asks for a "string literal". What does the word "literal" mean? asks about what that means, which links to the Wikipedia entry:
a literal is a notation for representing a fixed value in source code
"foo" is a string literal, 8 is a numeric literal. let s = "foo" is a statement that assigns the value of a string literal to an identifier (variable). println!(s) is a statement that provides an identifier to the macro.
If you really want to define the first argument of println! in one place, I found a way to do it. You can use a macro:
macro_rules! hello {() => ("hello")};
println!(hello!());
Doesn't look too useful here, but I wanted to use the same formatting in a few places, and in this case the method was very helpful:
macro_rules! cell_format {() => ("{:<10}")}; // Pads with spaces on right
// to fill up 10 characters
println!(cell_format!(), "Foo");
println!(cell_format!(), 456);
The macro saved me from having to duplicate the formatting option in my code.
You could also, obviously, make the macro more fancy and take arguments if necessary to print different things with different arguments.
If your format string will be reused only a moderate number of times, and only some variable data will be changed, then a small function may be a better option than a macro:
fn pr(x: &str) {
println!("Some stuff that will always repeat, something variable: {}", x);
}
pr("I am the variable data");
Outputs
Some stuff that will always repeat, something variable: I am the variable data
In Python, this would be final_char = mystring[-1]. How can I do the same in Rust?
I have tried
mystring[mystring.len() - 1]
but I get the error the type 'str' cannot be indexed by 'usize'
That is how you get the last char (which may not be what you think of as a "character"):
mystring.chars().last().unwrap();
Use unwrap only if you are sure that there is at least one char in your string.
Warning: About the general case (do the same thing as mystring[-n] in Python): UTF-8 strings are not to be used through indexing, because indexing is not a O(1) operation (a string in Rust is not an array). Please read this for more information.
However, if you want to index from the end like in Python, you must do this in Rust:
mystring.chars().rev().nth(n - 1) // Python: mystring[-n]
and check if there is such a character.
If you miss the simplicity of Python syntax, you can write your own extension:
trait StrExt {
fn from_end(&self, n: usize) -> char;
}
impl<'a> StrExt for &'a str {
fn from_end(&self, n: usize) -> char {
self.chars().rev().nth(n).expect("Index out of range in 'from_end'")
}
}
fn main() {
println!("{}", "foobar".from_end(2)) // prints 'b'
}
One option is to use slices. Here's an example:
let len = my_str.len();
let final_str = &my_str[len-1..];
This returns a string slice from position len-1 through the end of the string. That is to say, the last byte of your string. If your string consists of only ASCII values, then you'll get the final character of your string.
The reason why this only works with ASCII values is because they only ever require one byte of storage. Anything else, and Rust is likely to panic at runtime. This is what happens when you try to slice out one byte from a 2-byte character.
For a more detailed explanation, please see the strings section of the Rust book.
As #Boiethios mentioned
let last_ch = mystring.chars().last().unwrap();
Or
let last_ch = codes.chars().rev().nth(0).unwrap();
I would rather have (how hard is that!?)
let last_ch = codes.chars(-1); // Not implemented as rustc 1.56.1
I'm learning Rust and the chapter for structs gives an example of a struct without a ; at the end. It compiles but I have no idea why this is allowed.
fn main() {
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
}
... same question goes for functions, actually.
As Shepmaster said in the comment, the "reason" is that Rust defines so. Here I will explain the rules behind it.
Basically you can omit ; when it ends with }. This will answer your question.
However, there are a number of exceptions to the rule:
When {} appears indirectly
The rule above doesn't apply when {} appears indirectly, like
use std::io::{self, Read, Write}; // Here }; appears
or
let x = if cond {
1
} else {
2
}; // Here }; appears
In this case, {} isn't a direct part of use/let. So in this case you need ;.
Items
Items are things which you can also place outside of functions. That is, one of extern crate, use, mod, struct, enum, union, type, trait, impl, fn, static, const, extern, and macros.
You can place items either outside of functions or in a function. However, There is a difference between them:
If it appears outside of functions, you have to omit ; when unnecessary.
If it appears in a function, you can also place ; there. This is basically because the ; itself is an empty statement.
Example:
struct A {} // You can't place ; here
fn main() {
struct B {} // You can omit ; here
struct C {}; // You can also place ; here
}
The last expression
You have to omit ; if
It is the last statement in the block,
it is an expression (items and let aren't expressions), and
you want to return the value from the expression.
Example:
fn f() -> i32 {
let x = 1;
x + x // You want to return x + x, so you can't place `;` here
}
Block expressions
if, if let, match, loop, while, while let, for, unsafe, and bare {} ends with }, so you can omit ; after them. However, there is a slight effect if you place ; here.
Example:
fn f(x: i32) -> i32 {
if x < 10 {
10
} else {
20
}; // If you remove ; here, then you will see a compile error.
42
}
In most cases, you don't have to place ; here; instead you may have to place ; in the blocks.
fn f(x: i32) -> i32 {
if x < 10 {
10;
} else {
20;
}
42
}
Statement macros
In statement positions, you can write three different kinds of macros:
some_macro!()/some_macro![]: this isn't in fact a statement macro; instead, this is a mere expression macro. It can't expand to items or let.
some_macro!{}: this expands to zero or more statements.
some_macro!();/some_macro![];/some_macro!{};: this also expands to zero or more statements; however, there is a very minor difference: ; is added to the last expanded statement.