-
-
Notifications
You must be signed in to change notification settings - Fork 203
Add Strings concept #712
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Add Strings concept #712
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"authors": [ | ||
"colinleach" | ||
], | ||
"contributors": [], | ||
"blurb": "Strings are an immutable sequence of Unicode characters." | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
# About Strings | ||
|
||
A [`string`][ref-string] in Kotlin is an immutable sequence of Unicode characters. | ||
|
||
[`Immutable`][wiki-immutable] means that any operation on a string must return a new string: the original string can never change. | ||
|
||
[`Unicode`][wiki-unicode] means that most of the world's writing systems can be represented, but (in contrast to older languages such as C) there is no 1:1 mapping between characters and bytes. | ||
This will be discussed further in the [`Chars`][concept-chars] Concept. | ||
|
||
A string is surrounded by double-quotes `" "`. | ||
|
||
Some characters need escaping: `\\`, plus the usual non-printing characters such as `\t` (tab) and `\n` (newline). | ||
|
||
```kotlin | ||
val s = "Escape backslash \\." | ||
// Escape backslash \. | ||
``` | ||
|
||
Raw strings use 3 double-quotes, and can contain arbitrary text (no need for escaping). | ||
Multiline strings are also supported, including flexible handling of indents. | ||
|
||
```kotlin | ||
val multi = """I'm a | ||
|multi-line | ||
|string with special characters \ \t """ | ||
|
||
multi.trimMargin() // delimiter defaults to | but can be specified | ||
//I'm a | ||
//multi-line | ||
//string with special characters \ \t | ||
``` | ||
|
||
Strings can be concatenated with `+`, but this is best limited to short and simple cases. | ||
There are other and often better options. | ||
|
||
## String templates | ||
|
||
[`Templates`][ref-templates] refers to what some other languages call "interpolation". | ||
|
||
If a string contains a dollar sign `$`, followed by an identifier, or contains braces (`{expression}`) surrounding an expression, those are substituted by respectively the value or the result of the expression. | ||
|
||
```kotlin | ||
val x = 42 | ||
val st = "x is $x, x squared is {x * x}" | ||
// x is 42, x squared is 1764 | ||
``` | ||
|
||
## String formatting | ||
|
||
On the JVM platform (only), `String.format()` allows more precise formatting than string templates, with [syntax][web-formats] similar to the (_very old!_) [`printf`][wiki-printf] functions. | ||
|
||
```kotlin | ||
String.format("%s %.3f", "π ≈", 3.14159) | ||
//π ≈ 3.142 | ||
``` | ||
|
||
~~~~exercism/advanced | ||
Kotlin can be compiled to several different targets: the Java Virtual Machine, JavaScript, native binaries for Linux, Windows, Android and Apple, plus two variants of WebAssembly. | ||
|
||
Essentially the same code can be used for each, but different capabilities in the target platforms mean some differences in which standard library functions are supported. | ||
|
||
Exercism currently uses the JVM for testing. | ||
~~~~ | ||
|
||
## String functions | ||
|
||
Kotlin provides _many_ [`functions`][ref-string-functions] to manipulate strings. | ||
|
||
Mostly, these are [`extensions functions`][ref-extensions] rather than members of the `String` class, though this has little effect on how we use them. | ||
|
||
~~~~exercism/note | ||
Kotlin's rather complex [documentation][ref-string-functions] pages hide extension functions in the default view. | ||
At moment of writing this, the most valuable content is hidden in a tab named `Members and Extensions`. | ||
Click it to expand this section and see all the members and extensions available on the `String` class. | ||
|
||
[ref-string-functions]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/ | ||
~~~~ | ||
|
||
The following example shows just a small selection of what is available: | ||
|
||
```kotlin | ||
val str = "Hello World!" | ||
|
||
str.length // => 12 (a property, not a function) | ||
str.elementAt(6) // => W | ||
str.elementAtOrNull(20) // => null (index out of range) | ||
str.substring(6, 11) // => "World" | ||
|
||
str.lowercase() // => "hello world!" | ||
str.uppercase() // => "HELLO WORLD!" | ||
|
||
str.startsWith("Hel") // => true | ||
str.endsWith("xyz") // => false | ||
|
||
str.toCharArray() // => [H, e, l, l, o, , W, o, r, l, d, !] | ||
"42".toInt() + 1 // => 43 (parsing; see also toFloat) | ||
``` | ||
|
||
## Building a string | ||
|
||
Sometimes a long string needs to be built up in stages, for example within a loop. | ||
|
||
Concatenating strings with `+` soon becomes neither elegant nor performant: immutability means that there is a _lot_ of copying required. | ||
|
||
Kotlin has various more efficient ways to combine multiple string: | ||
|
||
- String templates, described above. | ||
- [`joinToString()][ref-jointostring], which will be covered in the [Lists][concept-lists] Concept. | ||
- Java's [`StringBuilder`][ref-stringbuilder], which is not regarded as particularly idiomatic Kotlin. | ||
- Kotlin's [`buildString()`][ref-buildstring], which wraps `StringBuilder` in a more concise and idiomatic syntax. | ||
This takes string-building logic as a lambda argument, which will be discussed in a later Concept. | ||
|
||
In essence, a `StringBuilder` is a list-like structure, with many convenient methods. | ||
This is a small selection: | ||
|
||
- [`append()`][ref-sb-append] to add to the end. | ||
- [`insert()`][ref-sb-insert] to add at a specified position. | ||
- [`deleteAt()`][ref-sb-deleteat] and [`deleteRange()`][ref-sb-deleterange] to remove from specified position(s). | ||
- `toString()` to convert to a normal string at the end: concatenating everything in a single, performant operation. | ||
|
||
```kotlin | ||
// Available, not recommended | ||
val sb = StringBuilder() | ||
sb.append("Hello ") | ||
sb.append("World!") | ||
sb.toString() | ||
//Hello World! | ||
``` | ||
|
||
A `buildString()` example, using syntax from later Concepts: | ||
|
||
```kotlin | ||
val countDown = buildString { | ||
for (i in 5 downTo 1) { | ||
append(i) | ||
append("_") | ||
} | ||
} | ||
// countDown is "5_4_3_2_1_" | ||
``` | ||
|
||
|
||
[ref-string]: https://kotlinlang.org/docs/strings.html | ||
[wiki-immutable]: https://en.wikipedia.org/wiki/Immutable_object | ||
[wiki-unicode]: https://en.wikipedia.org/wiki/Unicode | ||
[web-formats]: https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html#summary | ||
[wiki-printf]: https://en.wikipedia.org/wiki/Printf | ||
[ref-stringbuilder]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/-string-builder/ | ||
[ref-extensions]: https://kotlinlang.org/docs/extensions.html#extensions.md | ||
[ref-string-functions]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/ | ||
[concept-chars]: https://exercism.org/tracks/kotlin/concepts/chars | ||
[concept-lists]: https://exercism.org/tracks/kotlin/concepts/lists | ||
[ref-templates]: https://kotlinlang.org/docs/strings.html#string-templates | ||
[ref-sb-append]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/-string-builder/#9100522%2FFunctions%2F-705004581 | ||
[ref-sb-insert]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/-string-builder/#-132863384%2FFunctions%2F-705004581 | ||
[ref-sb-deleteat]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/-string-builder/#-386007892%2FFunctions%2F-956074838 | ||
[ref-sb-deleterange]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/-string-builder/#-1622040372%2FFunctions%2F-956074838 | ||
[ref-buildstring]: https://kotlinlang.org/docs/java-to-kotlin-idioms-strings.html#build-a-string | ||
[ref-jointostring]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.collections/join-to-string.html |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# Introduction | ||
|
||
A [`string`][ref-string] in Kotlin is an immutable sequence of Unicode characters. | ||
|
||
[`Immutable`][wiki-immutable] means that any operation on a string must return a new string: the original string can never change. | ||
|
||
[`Unicode`][wiki-unicode] means that most of the world's writing systems can be represented, but (in contrast to older languages such as C) there is no 1:1 mapping between characters and bytes. | ||
|
||
A string is usually surrounded by double-quotes `" "`. | ||
|
||
Some characters need escaping: `\'`, `\\`, plus the usual non-printing characters such as `\t` (tab) and `\n` (newline). | ||
|
||
```kotlin | ||
val s = "Escape apostrophe \' and backslash \\." | ||
// Escape apostrophe ' and backslash \. | ||
``` | ||
|
||
Raw strings use 3 double-quotes, and can contain arbitrary text (no need for escaping). | ||
Multiline strings are also supported, including flexible handling of indents. | ||
|
||
```kotlin | ||
val multi = """I'm a | ||
|multi-line | ||
|string with special characters \ \t """ | ||
|
||
multi.trimMargin() // delimiter defaults to | but can be specified | ||
//I'm a | ||
//multi-line | ||
//string with special characters \ \t | ||
``` | ||
|
||
Strings can be concatenated with `+`, but this is best limited to short and simple cases. | ||
There are other and often better options. | ||
|
||
## String templates | ||
|
||
This refers to what some other languages call "interpolation". | ||
|
||
If a string contains a dollar sign `$`, followed by an identifier, or contains braces (`{expression}`) surrounding an expression, those are substituted by respectively the value or the result of the expression. | ||
|
||
```kotlin | ||
val x = 42 | ||
val st = "x is $x, x squared is {x * x}" | ||
// x is 42, x squared is 1764 | ||
``` | ||
|
||
The braces `{ }` are needed around expressions when parsing would otherwise be ambiguous. | ||
|
||
In general, use of string templates is a more efficient and idiomatic way to combine strings than using `+`. | ||
|
||
## String functions | ||
|
||
Kotlin provides _many_ [`functions`][ref-string-functions] to manipulate strings. | ||
|
||
Mostly, these are [`extensions functions`][ref-extensions] rather than members of the `String` class, though this has little effect on how we use them. | ||
|
||
~~~~exercism/note | ||
Kotlin's rather complex [documentation][ref-string-functions] pages hide extension functions in the default view. | ||
Be sure to click `Members and Extensions` to expand this section. | ||
|
||
[ref-string-functions]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/ | ||
~~~~ | ||
|
||
The following example shows just a small selection of what is available: | ||
|
||
```kotlin | ||
val str = "Hello World!" | ||
|
||
str.length // => 12 (a property, not a function) | ||
str.elementAt(6) // => W | ||
str.elementAtOrNull(20) // => null (index out of range) | ||
str.substring(6, 11) // => "World" | ||
|
||
str.lowercase() // => "hello world!" | ||
str.uppercase() // => "HELLO WORLD!" | ||
|
||
str.startsWith("Hel") // => true | ||
str.endsWith("xyz") // => false | ||
|
||
str.toCharArray() // => [H, e, l, l, o, , W, o, r, l, d, !] | ||
"42".toInt() + 1 // => 43 (parsing; see also toFloat) | ||
``` | ||
|
||
|
||
[ref-string]: https://kotlinlang.org/docs/strings.html | ||
[wiki-immutable]: https://en.wikipedia.org/wiki/Immutable_object | ||
[wiki-unicode]: https://en.wikipedia.org/wiki/Unicode | ||
[ref-stringbuilder]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/-string-builder/ | ||
[ref-extensions]: https://kotlinlang.org/docs/extensions.html#extensions.md | ||
[ref-string-functions]: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
[ | ||
{ | ||
"url": "https://kotlinlang.org/docs/strings.html", | ||
"description": "Kotlin string introduction" | ||
}, | ||
{ | ||
"url": "https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/", | ||
"description": "String functions" | ||
}, | ||
{ | ||
"url": "https://kotlinlang.org/docs/strings.html#string-templates", | ||
"description": "String Templates" | ||
} | ||
] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.