Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the "standard" way to concatenate strings?

Tags:

rust

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:

  • What do I have to write to achieve the obvious?
  • What is the "standard" way to do this in Rust?
like image 637
BitTickler Avatar asked Jul 10 '15 02:07

BitTickler


People also ask

What is the correct way to concatenate the strings?

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.

What is the standard way to concatenate two strings in SQL?

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.

What is the most efficient way to concatenate many strings together?

The most efficient is to use StringBuilder, like so: StringBuilder sb = new StringBuilder(); sb. Append("string1"); sb.

What is the best way to concatenate strings in Python?

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.


2 Answers

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.

like image 52
George Hilliard Avatar answered Oct 28 '22 06:10

George Hilliard


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.

like image 40
bluss Avatar answered Oct 28 '22 08:10

bluss