Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rust String concatenation [duplicate]

Tags:

string

rust

I started programming with Rust this week and I am having a lot of problems understanding how Strings work.

Right now, I am trying to do a simple program that prints a list of players appending their order(for learning purposes only).

let res : String = pl.name.chars().enumerate().fold(String::new(),|res,(i,ch)| -> String {
    res+=format!("{} {}\n",i.to_string(),ch.to_string());
});

println!("{}", res);

This is my idea, I know I could just use a for loop but the objective is to understand the different Iterator functions.

So, my problem is that the String concatenation does not work.

   Compiling prueba2 v0.1.0 (file:///home/pancho111203/projects/prueba2)
src/main.rs:27:13: 27:16 error: binary assignment operation `+=` cannot be applied to types `collections::string::String` and `collections::string::String` [E0368]
src/main.rs:27             res+=format!("{} {}\n",i.to_string(),ch.to_string());
                           ^~~
error: aborting due to previous error
Could not compile `prueba2`.

I tried using &str but it is not possible to create them from i and ch values.

like image 315
Francisco Rubin Capalbo Avatar asked Jun 08 '15 16:06

Francisco Rubin Capalbo


People also ask

Does rust have string interpolation?

Short answer: no, not that type of interpolation.

What is str in Rust?

The str type, also called a 'string slice', is the most primitive string type. It is usually seen in its borrowed form, &str . It is also the type of string literals, &'static str . Strings slices are always valid UTF-8.


1 Answers

First, in Rust x += y is not overloadable, so += operator won't work for anything except basic numeric types. However, even if it worked for strings, it would be equivalent to x = x + y, like in the following:

res = res + format!("{} {}\n",i.to_string(),ch.to_string())

Even if this were allowed by the type system (it is not because String + String "overload" is not defined in Rust), this is still not how fold() operates. You want this:

res + &format!("{} {}\n", i, ch)

or, as a compilable example,

fn main(){
    let x = "hello";
    let res : String = x.chars().enumerate().fold(String::new(), |res, (i, ch)| {
        res + &format!("{} {}\n", i, ch)
    });

    println!("{}", res);
}

When you perform a fold, you don't reassign the accumulator variable, you need to return the new value for it to be used on the next iteration, and this is exactly what res + format!(...) do.

Note that I've removed to_string() invocations because they are completely unnecessary - in fact, x.to_string() is equivalent to format!("{}", x), so you only perform unnecessary allocations here.

Additionally, I'm taking format!() result by reference: &format!(...). This is necessary because + "overload" for strings is defined for String + &str pair of types, so you need to convert from String (the result of format!()) to &str, and this can be done simply by using & here (because of deref coercion).

In fact, the following would be more efficient:

use std::fmt::Write;

fn main(){
    let x = "hello";
    let res: String = x.chars().enumerate().fold(String::new(), |mut res, (i, ch)| {
        write!(&mut res, "{} {}\n", i, ch).unwrap();
        res
    });

    println!("{}", res);
}

which could be written more idiomatically as

use std::fmt::Write;

fn main(){
    let x = "hello";

    let mut res = String::new(); 
    for (i, ch) in x.chars().enumerate() {
        write!(&mut res, "{} {}\n", i, ch).unwrap();
    }

    println!("{}", res);
}

(try it on playpen)

This way no extra allocations (i.e. new strings from format!()) are created. We just fill the string with the new data, very similar, for example, to how StringBuilder in Java works. use std::fmt::Write here is needed to allow calling write!() on &mut String.

I would also suggest reading the chapter on strings in the official Rust book (and the book as a whole if you're new to Rust). It explains what String and &str are, how they are different and how to work with them efficiently.

like image 196
Vladimir Matveev Avatar answered Sep 27 '22 18:09

Vladimir Matveev