Rust backslash in '' not terminated - rust

in my rust program, I need to declare a mutable variable called start and assign it the value of a backslash later on.
let mut start = '\';
however, the compiler throws this error:
error[E0762]: unterminated character literal
--> src/main.rs:35:19
|
35 | let mut start = '\';
|
I have already tried using ``and "" instead of '' but the error persists. Why is this??

You have to escape the \ like so: '\\' to get a char or like this: "\\" if you want to have a &str
If you later want to edit that variable like the mut suggests you probably want a proper String like this:
String::from("\\")

Related

trim() on .collect::<String>() E0716 in Rust

Rust code:
let item_discount_price = item_discount_price_element.text().collect::<String>().trim();
give error:
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:64:35
|
64 | let item_discount_price = item_discount_price_element.text().collect::<String>().trim();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
65 | let item_discount_price = item_discount_price.trim();
| -------------------------- borrow later used here
|
= note: consider using a `let` binding to create a longer lived valu
I have solved it with following code:
let item_discount_price = item_discount_price_element.text().collect::<String>();
let item_discount_price = item_discount_price.trim();
For background I am doing some web-scraping, item_discount_price_element is ElementRef from scraper. https://docs.rs/scraper/latest/scraper/element_ref/struct.ElementRef.html
Question is why first code is not working ?
If you look at the documentation of trim() you'll notice that it's not a member of String but of str:
pub fn trim(&self) -> &str
That is, it takes a &str (string slice) and returns another &str, a subslice, with the same lifetime.
Now, your code is equivalent of doing something like:
let s: &str = String::from(" hello ").trim();
That would create a temporary String, borrow it as a &str, and compute its trim slice. Then the temporary is dropped and the trimmed slice reference is invalidated. Fortunately Rust lifetime rules prevents you from trying to use that invalid value.
If you save a temporary value in a variable you avoid dropping it, as you noticed in your code.
let s: String = String::from(" hello ");
let s: &str = s.trim();
And now the code does what you want.
If you do not need to ever use the temporary it is idiomatic in Rust to use the same name for both values, to illustrate that point, and to avoid having to think of two names (naming things is hard). Note that the first s still exists, it is not destroyed by having another variable with the same name, it is just shadowed, and it will be dropped normally at the end of its scope.

Why can't print a struct field with formatted print?

Like following code,
it does working to print values with formatted print, when values are primitive values or struct(with derive debug attribute), or something.
But I can't print values when values are struct fields.
#[derive(Debug)]
struct Point<T> {
x: T,
y: T,
}
fn main() {
let a = 3;
let p = Point { x: 5, y: 10 };
println!("{}", a); // Working
println!("{a}"); // Working
println!("{:?}", p); // Working
println!("{p:?}"); // Working
println!("{} {}", p.x, p.y); // Working
println!("{p.x} {p.y}"); // Not working
}
The error message is following.
error: invalid format string: expected `'}'`, found `'.'`
--> src/main.rs:18:17
|
18 | println!("{p.x} {p.y}"); // Not working
| - ^ expected `}` in format string
| |
| because of this opening brace
|
= note: if you intended to print `{`, you can escape it using `{{`
error: could not compile `rust-ex` due to previous error
I think that the type of p.x and p.y is i32 so they can printed with formatted print but it doesn't.
Is there any way to print struct fields with formatter print? Or is there anything need to implement?
Your problem is not a formatting problem, just an issue with what exactly println! accepts in its formatting string.
Contrary to what you may experience in other languages, the part between braces in the literal string in a println! is not a string escape, meaning that you could put any (printable) Rust expression. Instead, you should see it as a named parameter. Therefore, it can only be a variable name. println! also allows you to mimic variable definition if you don't already have a variable with that name, like this:
println!("{px}", px = p.x);
Another similar but different issue is trying to println! when you have a Rust variable that is an underscore:
let _ = 2;
println!("Value of _ is {_}");
The error is:
invalid format string: invalid argument name `_`
...
println!("Value of _ is {_}");
^ invalid argument name in format string
This is probably because the underscore is meant to be ignored
The underscore (_) is a reserved identifier in Rust and serves different purposes depending on the context. It usually means that something is ignored.
Other sites explain how in rust, the underscore does "not bind to the variable"; or "does not have ownership of the object"
See #jthulhu's comment --not only is _ meant to be ignored in Rust, the _ variable cannot be used in Rust; therefore isn't even allocated (that explains my error messages). This is different from other programming languages, where the _ variable is just a convention to signify the _ variable is meant to be ignored but could be used. In Rust, as #jthulhu says: "Basically, doing let _ = 3; will result in absolutely nothing even without optimizations"
I know the OP already found the best accepted answer. I just want to offer this answer in case other folks search for "invalid format string" or "invalid argument name _" and find this SO question.
If you tried a workaround like:
println!("Value of _ is {}", _);
Then you get a new error, reinforcing the idea that the underscore variable is never meant to be used:
in expressions, `_` can only be used on the left-hand side of an assignment
`_` not allowed here
So the underscore variable is allowed on the left-hand side of an assignment as in my code above, or this underscore expression where the _ signifies a placeholder in a destructuring assignment, but you can't reference the underscore variable later, including in println!. The only solution is to use a different variable name.

Programming in Rust , how to fix error[E0515] "cannot return value referencing local variable"?

Please help me to compile my code attached bellow. The compiler says that following 2 patterns depending on which lines I comment out.
The program reads a &str which is a simple "svg path command" like code then parses it. The pasted code has been simplified for simplicity. It uses Regex to split the input string into lines then study each line in the main for loop. Each loop pushes the parse result onto a vector. Finally the function returns the vector.
Basically the compiler says returning the vector is not allowed because it refers local variable. Though I don't have any workaround.
error[E0597]: `cmd` does not live long enough
--> src/main.rs:24:25
|
24 | codeV = re.captures(cmd.as_str());
| ----- ^^^ borrowed value does not live long enough
| |
| borrow might be used here, when `codeV` is dropped and runs the destructor for type `Option<regex::Captures<'_>>`
...
30 | }
| - `cmd` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are defined
error[E0515]: cannot return value referencing local variable `cmd`
--> src/main.rs:31:1
|
24 | codeV = re.captures(cmd.as_str());
| --- `cmd` is borrowed here
...
31 | V //Error
| ^ returns a value referencing data owned by the current function
Playground
use regex::Regex;
pub fn parse(path:&str) {//->Vec<Option<regex::Captures<>>> //Error
let reg_n=Regex::new(r"\n").unwrap();
let path=reg_n.replace_all("\n"," ");
let reg_cmd=Regex::new(r"(?P<cmd>[mlhv])").unwrap();
let path=reg_cmd.replace_all(&path,"\n${cmd}");
let cmdV=reg_n.split(&path);
//let cmdV:Vec<&str> = reg.split(path).map(|x|x).collect();
let mut V:Vec<Option<regex::Captures<>>>=vec![];
let mut codeV:Option<regex::Captures<>>=None;
let mut count=0;
for cmd_f in cmdV{//This loop block has been simplified.
count+=1;
if count==1{continue;}
let mut cmd="".to_string();
cmd=cmd_f.to_string();
cmd=cmd.replace(" ","");
let re = Regex::new(r"\{(?P<code>[^\{^\}]{0,})\}").unwrap();
codeV = re.captures(cmd.as_str());
//cmd= re.replace_all(cmd.as_str(),"").to_string();
let cmd_0=cmd.chars().nth(0).unwrap();
//cmd.remove(0);
//V.push(codeV); //Compile error
V.push(None); //OK
}
//V
}
fn main() {
parse("m {abcd} l {efgh}");
}
Though I don't have any workaround.
regex's captures refer to the string they matched for efficiency. This means they can't outlive that string, as the match groups are essentially just offsets into that string.
Since the strings you match are created in the loop body, this means captures can't escape the loop body.
Aside from not creating strings in the loop body (or even the function), the solution / workaround is to convert your capture groups to owned data and store that: instead of trying to return a vector of captures, extract from the capture the data you actually want, convert it to an owned String (or tuple thereof, or whatever), and push that onto your vector.
e.g. https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=0107333e30f831a418d75b280e9e2f31
you can use cmd.clone().as_str() if you not sure the value has borrowed or no

Use write! macro with a string instead of a string literal

I've written the following function:
fn print_error(text: &str) {
let mut t = term::stdout().unwrap();
t.fg(term::color::RED).unwrap();
(write!(t, text)).unwrap();
assert!(t.reset().unwrap());
}
It should take the string and print it out on the console in red.
When I try to to compile, the compiler says:
error: format argument must be a string literal.
--> src/main.rs:4:16
|
4 | (write!(t, text)).unwrap();
| ^^^^
After a lot of searching, I've found out that I'm able to replace the text variable with e.g. "text" and it will work because it's a string literal, which the write! macro needs.
How could I use the write! macro with a string instead of a string literal? Or is there a better way to colourize the terminal output?
Just use write!(t, "{}", text).
I think you're missing the thrust of the error message. write! has two mandatory arguments:
A location to write to.
A format string.
The second parameter is not just any arbitrary string, it's the format string.
See also:
println! error: expected a literal / format argument must be a string literal

A more convenient concatenation with a string literal in Rust

In the nightly Rust it is no longer possible to designate a string literal as String with a "~" character.
In C++, for example, I'm using user-defined literals to concatenate string literals without the crust of mentioning std::string every time:
inline std::string operator"" _s (const char* str, size_t size) {return std::string (str, size);}
foo ("Hello, "_s + "world!");
Is there a similar feature existing or planned in Rust to make string literal concatenation less painful than String::from_str ("Hello, ") + "world!"?
If you literally (hah) have string literals, you can use the concat! macro:
let lit = concat!("Hello, ", "world!")
You can natively split strings over several lines:
let lit = "Hello, \
World";
The \ consumes all following whitespace, including the leading spaces on the next line; omitting the \ will include the string data "verbatim", with newlines and leading spaces etc.
You can add a &str to a String:
let s = "foo".to_string() + "bar" + "baz";
You could use push_str iteratively:
let mut s = "foo".to_string();
s.push_str("bar");
s.push_str("baz");
You could use SliceConcatExt::concat:
let s = ["foo", "bar", "baz"].concat();
If all else fails, you can define a macro to do exactly what you want.
See also:
How to concatenate static strings in Rust
What is the syntax for a multiline string literal?
How do I concatenate strings?
You can use the format! macro. It is more readable, more translation-friendly, more efficient, and more powerful (you can concatenate more than just strings, just like C++'s ostringstream). It is also completely type-safe.
format!("Hello, {}", "world!")
You can also use named arguments to improve readability.
format!("hello, {who}", who = "world")
The full formatting syntax is described in std::fmt.
Rust does not have user-defined literals. I think adding such a feature is backward-compatible, so maybe this feature will be added after Rust 1.0.
You can concatenate str literals without using String with the concat! macro:
let input = concat!("Hello", ' ', "world");
To make it a string, specify the destination type and use into:
let input: String = concat!("Hello", ' ', "world").into();
Full program:
fn main() {
let input: String = concat!("Hello", ' ', "world").into();
println!("{}", input); // Output: Hello world
}

Resources