# Text.Concat

> Joins a list of values into one string with NOTHING between the elements. It is Text.Join with no separator, and the same operation as string.Concat. A single non-list value is converted on its own. Runs in memory.

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

## Summary        {#summary}
`Text.Concat(values)` runs the elements of `values` together into one string, with **nothing** between them. It is
[Text.Join](https://osysharp.com/reference/function/text-join/) with an empty separator, and identical to `string.Concat(values)`.

Reach for it when the pieces already carry whatever punctuation they need — path segments that end in `/`, pre-formatted
fragments, an accumulated list of chunks. When you want something *between* the elements, use `Text.Join`.

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

Each element is converted to its string form first, exactly as string interpolation would convert it.

## Description    {#description}

### It is `Text.Join` with no separator   {#vs-join}
The two are the same operation and differ only in what falls between the elements — nothing, versus the separator you
name. `Text.Concat(parts)` and `Text.Join("", parts)` produce identical output; prefer `Concat`, which says the
intent without an empty-string argument to read past.

### An empty list yields the empty string   {#empty-list}
There is nothing to run together, so the result is `""` — not null. That means a `Concat` over a filtered list stays
safe when the filter matched nothing, with no length check first.

### A single value is converted on its own   {#single-value}
Passed one non-list value, it converts that value and returns it. That makes it usable as a plain "to string" in code
that sometimes holds a list and sometimes holds one item, without branching.

### It runs in memory, on whichever side the cursor is already on   {#execution-side}
Like the rest of `Text.*`, it is a pure in-memory operation — no round trip, and no hand-off. A component may call it
while rendering; a server function may call it mid-body. See [execution side](https://osysharp.com/reference/function/execution-side/).

## Examples       {#examples}

```osy title="running pre-punctuated pieces together" test app=text-concat
entity Doc {
  [Required, MaxLength(200)] string Title;
  security { allow read when IsAuthenticated || IsAnonymous; allow create, update when IsAuthenticated || IsAnonymous; }
}

// The segments already carry their own separators, so anything BETWEEN them would be wrong.
string BuildPath(string[] segments) {
  return Text.Concat(segments);
}

// An empty list is the empty string — no length check needed before calling.
string Nothing() {
  return Text.Concat([]);
}
```

## See also       {#see-also}
- [Text.Join](https://osysharp.com/reference/function/text-join/) — the same operation with something between the elements
- [String interpolation & format specifiers](https://osysharp.com/reference/function/string-interpolation/) — `$"{a}{b}"`, which is usually clearer for a fixed, known set of pieces
- [Text.Split](https://osysharp.com/reference/function/text-split/) — the inverse direction
