The `ImmutableString` Type ========================== {{#include ../links.md}} ~~~admonish question.side "Why `SmartString`?" [`SmartString`] is used because many strings in scripts are short (fewer than 24 ASCII characters). ~~~ All [strings] in Rhai are implemented as `ImmutableString`, which is an alias to `Rc` (or `Arc` under the [`sync`] feature). An `ImmutableString` is immutable (i.e. never changes) and therefore can be shared among many users. Cloning an `ImmutableString` is cheap since it only copies an immutable reference. Modifying an `ImmutableString` causes it first to be cloned, and then the modification made to the copy. Therefore, direct string modifications are expensive. Avoid `String` Parameters ------------------------- `ImmutableString` should be used in place of `String` for function parameters because using `String` is very inefficient (the argument is cloned during every function call). A alternative is to use `&str` which de-sugars to `ImmutableString`. A function with the first parameter being `&mut String` does not match a string argument passed to it, which has type `ImmutableString`. In fact, `&mut String` is treated as an opaque [custom type]. ```rust fn slow(s: String) -> i64 { ... } // string is cloned each call fn fast1(s: ImmutableString) -> i64 { ... } // cloning 'ImmutableString' is cheap fn fast2(s: &str) -> i64 { ... } // de-sugars to above fn bad(s: &mut String) { ... } // '&mut String' will not match string values ``` Differences from Rust Strings ----------------------------- Internally Rhai strings are stored as UTF-8 just like Rust (they _are_ Rust `String`s!), but nevertheless there are major differences. In Rhai a [string] is semantically the same as an array of Unicode characters and can be directly indexed (unlike Rust). This is similar to most other languages (e.g. JavaScript, C#) where strings are stored internally not as UTF-8 but as arrays of UCS-16 or UCS-32. Individual characters within a Rhai string can also be replaced just as if the string is an array of Unicode characters. In Rhai, there are also no separate concepts of `String` and `&str` (a string slice) as in Rust. ```admonish warning "Performance considerations" Although Rhai exposes a [string] as a simple array of [characters] which can be directly indexed to get at a particular [character], such convenient syntax is an _illusion_. Internally the [string] is still stored in UTF-8 (native Rust `String`s). All indexing operations actually require walking through the entire UTF-8 string to find the offset of the particular [character] position, and therefore is _much_ slower than the simple array indexing for other scripting languages. This implementation detail is hidden from the user but has a performance implication. Avoid large scale [character]-based processing of [strings]; instead, build an actual [array] of [characters] (via the `split()` method) which can then be manipulated efficiently. ```