This question already has answers here:
How to format a const string
(2 answers)
Is there a static alternative of format!()?
(3 answers)
Closed 9 months ago.
I have a simple template like "hello {blank} how are you?"
and 2 separate functions that need to hard code "blank" with static values (can be known at compile time).
I don't want to hard code this templated text to the functions.
I'm looking for something like a C #DEFINE macro which will just "stick" the value into the string.
Contrived:
// my macro/ const function or what ever needs to be here:
const fn / macro! fill_text(name: &str) -> {return format!("hello {name} how are you") } // at compile time should be evaluated, not at run time
fn say_hello_to_john() ->&'static str {
fill_text("john")
}
fn say_hello_to_jane() -> &'static str {
fill_text("jane")
}
Tried this but it doesn't yield a static string:
macro_rules! fill_text {
$text:expr => {
format!("hello {} how are you", $text) // how to make this static?
}
}
Related
This question already has answers here:
How can I port C++ code that uses the ternary operator to Rust?
(3 answers)
How do I idiomatically convert a bool to an Option or Result in Rust?
(4 answers)
Closed 1 year ago.
In C, there is the conditional operator on the form int x = foo > bar ? 1 : 0;. According to this issue, that seems to be something the Rust developers do not want to implement. If one wants to be concise: Is there a Rust equivalent/shorthand version to do the same?
struct Config {
timeout: Option<u32>,
}
impl Config {
// C-style conditional operator
pub fn new(timeout: u32) {
Config {
timeout == 0 ? None : Some(timeout)
}
}
// My attempted Rust approach
pub fn new(timeout: u32) {
let mut t = None;
if timeout != 0 {
t = Some(timeout);
}
Config { timeout: t }
}
}
fn main() {
let config = Config::new(0);
}
I guess I have two problems with the Rust approach as of now: 1) I need to create a new variable which is very hard to name anything meaningful and 2) the code is less concise than the C-style conditional operator (though perhaps more explicit).
This question already has answers here:
How do I create a global, mutable singleton?
(7 answers)
How to create a static string at compile time
(3 answers)
What are the differences between Rust's `String` and `str`?
(14 answers)
Closed 2 years ago.
There is a ALPHABET for arithmetic, it's const and used in a lot of functions. I want make the ALPHABET global, static, and const. Some functions need the ALPHABET type as &String, but str.to_string() function will happen once memory copy. this function is called frequently, so it's not good.
The used function is a library, can't change it.
static ALPHABET: &str = "xxxxxxxxxxxxxxxxxxxxxxx";
fn some1(value: &String, alphabet: &String) -> String {
xxxx
}
fn main() {
some1("test", ALPHABET); // Can't build
some1("test", &ALPHABET.to_string()); // OK, but will happend memory copy.
}
How use the ALPHABET without to_string() function?
It would be better if your function uses &str instead:
fn some1(value: &str, alphabet: &str) -> String {
xxxx
}
Playground
Since this is in a library you cannot modify, you could use lazy_static to instantiate a static reference to the String:
use lazy_static::lazy_static; // 1.4.0
lazy_static! {
static ref APLHABET: String = "xxxxxxxxxxxxxxxxxxxxxxx".to_string();
}
Playground
This question already has answers here:
How to match a String against string literals?
(8 answers)
What are the differences between Rust's `String` and `str`?
(14 answers)
Closed 4 years ago.
I'm new to Rust (1.31) and I would like to understand a simple piece of code that does not compile:
fn main() {
s = String::from("foo");
match s {
"foo" => {
println!("Yes");
}
_ => {
println!("No");
}
}
}
The error associated is :
10 | "foo" => {
| ^^^^^ expected struct `std::string::String`, found reference
After this error, I decided to change the code to :
fn main() {
let s = String::from("foo");
match s {
String::from("foo") => {
println!("Yes");
}
_ => {
println!("No");
}
}
}
By doing so, I was hoping to have the correct type, but it is not the case :
10 | String::from("foo") => {
| ^^^^^^^^^^^^^^^^^^^ not a tuple variant or struct
I am quite puzzled with this message from the compiler, at the end I managed to make it work by implementing :
fn main() {
let s = String::from("foo");
match &s as &str {
"foo" => {
println!("Yes");
}
_ => {
println!("No");
}
}
}
However, I do not understand the underlying mechanisms that make this solution the right one and why my second example does not work.
The first example doesn't work, because s is of type String, which is a string variant that owns the data in it. It is matched against a string literal (which can be be used as type &str). match doesn't understand how to compare those two different types, so it errors.
However String dereferences to &str, by implementing Deref<Target=str>, which means references to String can be used where a &str is required, e.g. for comparing it to one. That's what happens in the third example. By creating the reference &s, the implicit deref can happen, and the two types get comparable.
You can achieve the same thing with a little less magic by using the explicit method which creates a &str from String:
fn main() {
let s = String::from("foo");
match s.as_str() {
"foo" => {
println!("Yes");
},
_ => {
println!("No");
}
}
}
The second example tries to make things comparable making String the common type instead of &str. It doesn't work, because match expects a pattern on the left side, and not a function call which creates a new struct (and which also allocates behind the scene). Even if it would work (e.g. by moving the String creation outside of the match), the approach would be less desirable, because the new String would require a memory allocation.
This question already has an answer here:
How can I append a formatted string to an existing String?
(1 answer)
Closed 5 years ago.
See this example:
fn concat<T: std::fmt::Display>(s: &mut String, thing: T) {
// TODO
}
fn main() {
let mut s = "Hello ".into();
concat(&mut s, 42);
assert_eq!(&s, "Hello 42");
}
I know that I can use this:
s.push_str(&format!("{}", thing))
but this is not the most efficient, because format! allocate a String that is not necessary.
The most efficient is to write directly the string representation of the displayable item into the String buffer. How to do this?
There are multiple formatting macros, and in your case you want the write! macro:
use std::fmt::{Display, Write};
fn concat<T: Display>(s: &mut String, thing: &T) {
write!(s, "{}", thing).unwrap();
}
fn main() {
let mut s = "Hello ".into();
concat(&mut s, &42);
assert_eq!(&s, "Hello 42");
}
Anything that implements one of the Write trait (and String does) is a valid target for write!.
Note: actually anything that implements a write_fmt method, as macro don't care much about semantics; which is why either fmt::Write or io::Write work.
This question already has answers here:
How to prefix/suffix identifiers within a macro? [duplicate]
(3 answers)
Can a Rust macro create new identifiers?
(4 answers)
Is it possible to declare variables procedurally using Rust macros?
(4 answers)
Closed 5 years ago.
I need to generate setters and getters for my FFI code.
Is there a way I can append the variable name to the setter and getter function names in a macro? I tried stringify!($var + set) but it generated a bunch of errors.
Is hiding it in a module for each variable the only way?
macro_rules! gen {
($var:ident: $type:ident) => {
pub fn set(new_val: $type) {
unsafe { $var = new_val; }
}
pub fn get() -> $type {
unsafe { $var }
}
}
}
gen!(myvar1: u32);
gen!(myvar2: i32);
For myvar1 the setter and getter would be myvar1_set and myvar1_get respectively.