While I understand basically what str
and std::string::String
are and how they relate to each other, I find it a bit cumbersome to compose strings out of various parts without spending too much time and thought on it. So as usual I suspect I did not see the proper way to do it yet, which makes it intuitive and a breeze.
let mut s = std::string::String::with_capacity(200);
let precTimeToJSON = | pt : prectime::PrecTime, isLast : bool | {
s.push_str(
"{ \"sec\": "
+ &(pt.sec.to_string())
+ " \"usec\": "
+ &(pt.usec.to_string())
+ if isLast {"}"} else {"},"})
};
The code above is honored by the compiler with error messages like:
src\main.rs:25:20: 25:33 error: binary operation
+
cannot be applied to type&'static str
[E0369]
And even after half an hours worth of fiddling and randomly adding &
, I could not make this compilable. So, here my questions:
You concatenate strings by using the + operator. For string literals and string constants, concatenation occurs at compile time; no run-time concatenation occurs. For string variables, concatenation occurs only at run time.
To append a string to another and return one result, use the || operator. This adds two strings from the left and right together and returns one result. If you use the name of the column, don't enclose it in quotes. However, in using a string value as a space or text, enclose it in quotes.
The most efficient is to use StringBuilder, like so: StringBuilder sb = new StringBuilder(); sb. Append("string1"); sb.
One of the most popular methods to concatenate two strings in Python (or more) is using the + operator. The + operator, when used with two strings, concatenates the strings together to form one.
The Rust compiler is right (of course): there's no +
operator for string literals.
I believe the format!()
macro is the idiomatic way to do what you're trying to do. It uses the std::fmt
syntax, which essentially consists of a formatting string and the arguments to format (a la C's printf
). For your example, it would look something like this:
let mut s: String = String::new();
let precTimeToJSON = | pt : prectime::PrecTime, isLast : bool | {
s = format!("{{ \"sec\": {} \"usec\": {} }}{}",
pt.sec,
pt.usec,
if isLast { "" } else { "," }
)
};
Because it's a macro, you can intermix types in the argument list freely, so long as the type implements the std::fmt::Display
trait (which is true for all built-in types). Also, you must escape literal {
and }
as {{
and }}
, respectively. Last, note that the format string must be a string literal, because the macro parses it and the expanded code looks nothing like the original format!
expression.
Here's a playground link to the above example.
Two more points for you. First, if you're reading and writing JSON, have a look at a library such as rustc-serialize. It's much less painful!
Second, if you just want to concatenate &'static str
strings (that is, string literals), you can do that with zero run-time cost with the concat!()
macro. It won't help you in your case above, but it might with other similar ones.
Itertools::format
can help you write this as a single expression if you really want to.
let times: Vec<PrecTime>; // iterable of PrecTime
let s = format!("{}", times.iter().format(",", |pt, f|
f(&format_args!(r#"{{ "sec": {}, "usec": {} }}"#, pt.sec, pt.usec))
));
format()
uses a separator, so just specify ","
there (or ""
if you need no separator). It's a bit involved so that the formatting can be completely lazy and composable. You receive a callback f
that you call back with a &Display
value (anything that can be Display formatted).
Here we demonstrate this great trick of using &format_args!()
to construct a displayable value. This is something that comes in handy if you use the debug builder API as well.
Finally, use a raw string so that we don't need to escape the inner "
in the format: r#"{{ "sec": {} "usec": {} }}"#
. Raw strings are delimited by r#"
and "#
(free choice of number of #
).
Itertools::format()
uses no intermediate allocations, it is all directly passed on to the underlying formatter object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With