Asked  7 Months ago    Answers:  5   Viewed   39 times

Why does Rust have String and str? What are the differences between String and str? When does one use String instead of str and vice versa? Is one of them getting deprecated?

 Answers

30

String is the dynamic heap string type, like Vec: use it when you need to own or modify your string data.

str is an immutable1 sequence of UTF-8 bytes of dynamic length somewhere in memory. Since the size is unknown, one can only handle it behind a pointer. This means that str most commonly2 appears as &str: a reference to some UTF-8 data, normally called a "string slice" or just a "slice". A slice is just a view onto some data, and that data can be anywhere, e.g.

  • In static storage: a string literal "foo" is a &'static str. The data is hardcoded into the executable and loaded into memory when the program runs.

  • Inside a heap allocated String: String dereferences to a &str view of the String's data.

  • On the stack: e.g. the following creates a stack-allocated byte array, and then gets a view of that data as a &str:

    use std::str;
    
    let x: &[u8] = &[b'a', b'b', b'c'];
    let stack_str: &str = str::from_utf8(x).unwrap();
    

In summary, use String if you need owned string data (like passing strings to other threads, or building them at runtime), and use &str if you only need a view of a string.

This is identical to the relationship between a vector Vec<T> and a slice &[T], and is similar to the relationship between by-value T and by-reference &T for general types.


1 A str is fixed-length; you cannot write bytes beyond the end, or leave trailing invalid bytes. Since UTF-8 is a variable-width encoding, this effectively forces all strs to be immutable in many cases. In general, mutation requires writing more or fewer bytes than there were before (e.g. replacing an a (1 byte) with an รค (2+ bytes) would require making more room in the str). There are specific methods that can modify a &mut str in place, mostly those that handle only ASCII characters, like make_ascii_uppercase.

2 Dynamically sized types allow things like Rc<str> for a sequence of reference counted UTF-8 bytes since Rust 1.2. Rust 1.21 allows easily creating these types.

Tuesday, June 1, 2021
 
iftheshoefritz
answered 7 Months ago
62

"A very simple case to consider is when the algorithms applied to the real-time data and to the historical data are identical. Then it is clearly very beneficial to use the same code base to process historical and real-time data, and therefore to implement the use-case using the Kappa architecture". "Now, the algorithms used to process historical data and real-time data are not always identical. In some cases, the batch algorithm can be optimized thanks to the fact that it has access to the complete historical dataset, and then outperform the implementation of the real-time algorithm. Here, choosing between Lambda and Kappa becomes a choice between favoring batch execution performance over code base simplicity". "Finally, there are even more complex use-cases, in which even the outputs of the real-time and batch algorithm are different. For example, a machine learning application where generation of the batch model requires so much time and resources that the best result achievable in real-time is computing and approximated updates of that model. In such cases, the batch and real-time layers cannot be merged, and the Lambda architecture must be used".

Quote

Lambda-Architecture

  • Seperate Batch and Stream-Layer
  • Higher code complexity
  • Faster performance with seperate batch/stream
  • better for different algorithms in batch and stream
  • cheaper with a data storage for batch-computing instead of a database

Kappa-Architecture

  • only a steam processing layer
  • easier to maintain, lower complexity, single algorithm for batch and stream
  • too much data would be expensive if recomputed from a database for batch
  • too much data would be slower to process if recomputed from database or from kafka for batch
Saturday, August 14, 2021
 
tompave
answered 4 Months ago
26

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.

Monday, August 16, 2021
 
Dobz
answered 4 Months ago
31

I've succeeded to run the non-optimised code without abnormalities. Thanks to Notlikethat for the idea. My stack was just mapped into readonly memory.

So I've just added the offset statement into my linker script (". = 1024M;") in order to make all the symbols to start from 1GiB (where RAM begins). After this modification the code started to work properly.

Monday, August 23, 2021
 
cletus
answered 4 Months ago
74

The first contains a bundled ADT version of Eclipse.

This is simply a packaging convenience. You are welcome to obtain Eclipse separately and add Android tooling to it.

Android Studio, the second IDE, is based on IntelliJ.

At the present time, this is an early-access preview. IMHO, it is not suited for someone who does not have experience in Android application development.

Apart from these differences I can't get if there is anything that I can do with only one of them

At the present time, Android Studio is an early-access preview, meaning that there are lots of things that it does not have integrated in. Now, by this time next year, and hopefully far sooner, Android Studio will have equivalent or superior integration than does Eclipse with the ADT plugin.

and what's the point of having two distinct official IDEs.

There are an infinite number of "official" tools. You are welcome to use a plain text editor and tools outside of any IDE, for example.

You are welcome to watch the Google I|O 2013 video on developer tools, where they describe a bit of the rationale behind the development of Android Studio.

Thursday, October 7, 2021
 
Zulakis
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share