# Text.Join

> Joins a list of values into one string, placing the separator between each pair. It is the inverse of Text.Split, and the same operation as string.Join. An empty list yields the empty string, and a single-element list yields just that element — the separator only ever falls BETWEEN elements. Runs in memory.

<!-- id: function-text-join · area: function · stability: stable · html: https://osysharp.com/reference/function/text-join/ -->

## Summary        {#summary}
`Text.Join(separator, values)` concatenates the elements of `values` into a single string, inserting
`separator` **between** each adjacent pair. It is the inverse of [Text.Split](https://osysharp.com/reference/function/text-split/), and identical to
`string.Join(separator, values)`.

## Signature      {#signature}
```osy syntax
Text.Join(<string> separator, <list> values) -> string
string.Join(<string> separator, <list> values) -> string   // the same operation
```

## Description    {#description}
The separator goes **only between** elements, never at the ends: joining `["a", "b", "c"]` with `", "` gives
`"a, b, c"` — two separators for three elements. Two consequences follow directly:

- an **empty** list joins to `""` (no elements, so no separators);
- a **single-element** list joins to just that element (nothing to put a separator between).

An **empty separator** simply concatenates: `Text.Join("", ["a", "b"])` is `"ab"`.

`Text.Join` and `Text.Split` are exact inverses when the separator does not itself appear inside an element:
splitting on `", "` and re-joining on `", "` returns the original string. `Text.Join` runs **in memory** — it
builds one string from a set of values already in hand.

## Examples       {#examples}
```osy title="re-join a split string — Join is Split's inverse" test app=text-join
// Split a CSV line, drop the empties, and re-join with a cleaner separator.
string Reflow(string csv) {
  return Text.Join(" · ", Text.Split(csv, ","));
}
```

```osy title="the exact answers, pinned" run app=text-join
[Test]
void Text_join_answers() {
  Assert.Equal("a · b · c", Reflow("a,b,c"));

  // Round-trip: split then join on the same separator returns the original.
  Assert.Equal("one, two, three", Text.Join(", ", Text.Split("one, two, three", ", ")));

  // A single element gets no separator; an empty separator just concatenates.
  Assert.Equal("solo", Text.Join(", ", Text.Split("solo", ",")));
  Assert.Equal("ab", Text.Join("", Text.Split("a,b", ",")));
}
```

## See also       {#see-also}
- [Text.Split](https://osysharp.com/reference/function/text-split/) — the inverse: string → list
- [String interpolation & format specifiers](https://osysharp.com/reference/function/string-interpolation/) — `$"{a}-{b}"`, the other way to build a string from values
- [Text.Length, Text.IsEmpty, Text.IsBlank, Text.Contains, Text.StartsWith, Text.EndsWith](https://osysharp.com/reference/function/text-inspect/) — asking questions about the resulting string
