# String Slice

#### Synopsis

Retrieve a slice of a string.

#### Syntax

`Exp₁ [ Exp₂ .. Exp₄]`

`Exp₁ [ Exp₂ , Exp3 .. Exp₄]`

where `Exp₂`

and `Exp₄`

are optional.

#### Types

`Exp₁` | `Exp₂` | `Exp₃` | `Exp₄` | `Exp₁ [ Exp₂ .. Exp₄ ]` or `Exp₁ [ Exp₂ , Exp₃ .. Exp₄]` |
---|---|---|---|---|

`str` | `int` | `int` | `int` | `str` |

#### Description

A String slice is similar to a list Slice and uses the integer values of *Exp*₂ and *Exp*₄ to determine the `begin`

(*inclusive*) and `end`

(*exclusive*)
of a slice from the string value *S* of *Exp*₁. Negative indices count from the end of the string backwards.
Using the second form, an extra index *Exp*₃ is given that determines the
index of the second element in the slice and establishes the `step`

between
successive elements in the slice. The default `step`

is 1.
If `end`

is smaller than `begin`

, the slice is constructed backwards.

Let `Len`

be the length of *S* and let *N*₂, *N*₃ and *N*₄ be the respective values of the expressions
*Exp*₂, *Exp*₂ and *Exp*₂ when they are present.

The slice parameters `begin`

, `end`

, and `step`

are determined as follows:

*Exp₂*:**If**Otherwise, if*Exp₂*is absent, then`begin = 0`

.*N₂*>= 0 then`begin = N₂`

else`begin = N₂ + Len`

.*Exp₄*:**If**Otherwise, if*Exp₄*is absent, then`end = Len`

.*N₄*>= 0, then`end = N₄`

else`end = N₄ + Len`

.*Exp₃*:**If**Otherwise, if*Exp₃*is absent, then if`begin < end`

then`step = 1`

else`step = -1`

.`begin < end`

, then`step = N₃ - begin`

else`step = begin - N₃`

.

Now, the constraints `0 <= begin < Len`

and `0 < end < Len`

should hold,
otherwise the exception `IndexOutOfBounds`

is thrown.

The slice consists of the elements `S[begin]`

, `S[begin+step]`

, `S[end - step]`

.
When `begin >= end`

, the elements are listed in reverse order.

#### Examples

Consider the string `S = "abcdefghi";`

(with size 9) as running example.

Here is a view on *L* that will help to correlate positive and negative indices:

`i` | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|---|

`S[i]` | `"a"` | `"b"` | `"c"` | `"d"` | `"e"` | `"f"` | `"g"` | `"h"` | `"i"` |

`-i` | -9 | -8 | -7 | -6 | -5 | -4 | -3 | -2 | -1 |

Some common use cases (with `begin`

<= `end`

):

Slice | Means: |
---|---|

`S[begin..end]` | characters with indices `begin` through `end-1` |

`S[begin..]` | characters with indices `begin` through the rest of the string |

`S[..end]` | characters with indices from the beginning through `end-1` |

`S[..]` | the whole list |

`S[-1]` | last element of the string |

`S[-2..]` | the last two characters of the string |

`S[..-2]` | all characters except the last two. |

Let's put this into practice now.

`rascal>S = "abcdefghi";`

str: "abcdefghi"

---

abcdefghi

---

Slices with begin < end

`rascal>S[1..3];`

str: "bc"

---

bc

---

rascal>S[1..]; // empty end => end of string

str: "bcdefghi"

---

bcdefghi

---

rascal>S[..3]; // empty begin => first character of string

str: "abc"

---

abc

---

rascal>S[..]; // both empty => whole string

str: "abcdefghi"

---

abcdefghi

---

Slices with begin >= end

`rascal>S[3..1]; // slice contains characters with indices 3 and 2 (in that order)`

str: "dc"

---

dc

---

rascal>S[3..3]; // empty slice when begin == end

str: ""

---

---

Slices with negative begin or end:

`rascal>S[2..-2]; // equivalent to S[2..7]`

str: "cdefg"

---

cdefg

---

rascal>S[2..7];

str: "cdefg"

---

cdefg

---

rascal>S[-4..-2]; // equivalent to S[5..7]

str: "fg"

---

fg

---

rascal>S[5..7];

str: "fg"

---

fg

---

Slices with an explicit second index:

`rascal>S[1,3..6];`

str: "bdf"

---

bdf

---

rascal>S[5,3..];

str: "fdb"

---

fdb

---

Slicing does not go "out of bounds"; it just stops at the end if you go beyond the end or the beginning:

`rascal>S[..10];`

str: "abcdefghi"

---

abcdefghi

---

rascal>S[..-11];

str: "a"

---

a

---