Gleam Strings

Strings store text in Gleam. Every name, message, URL, and label in your program is a string. Gleam strings are immutable, UTF-8 encoded, and backed by an efficient binary representation inherited from Erlang.

Creating Strings

Wrap text in double quotes to create a string:

let city = "Bengaluru"
let greeting = "Hello, World!"
let empty = ""
let number_as_text = "42"

Note that "42" is a String, not an Int. The quotes make it text. You cannot perform arithmetic on it without converting it first.

String Concatenation

Join two strings together with the <> operator:

let first_name = "Ananya"
let last_name = "Sharma"
let full_name = first_name <> " " <> last_name
// full_name = "Ananya Sharma"

Concatenation Diagram
──────────────────────────────────────────────
"Ananya" <> " " <> "Sharma"
    │           │       │
    └─────┬─────┘       │
      "Ananya "   <>  "Sharma"
              └────┬────┘
             "Ananya Sharma"

String Length

Use the gleam/string module to measure a string's length in characters:

import gleam/string

let name = "Gleam"
let len = string.length(name)   // 5

Gleam counts Unicode characters, not raw bytes. The emoji "🎉" has a byte length of 4 but a character length of 1. string.length gives you the character count — what users actually see.

Common String Functions


string Module — Frequently Used Functions
──────────────────────────────────────────────────────────────
Function                │ What It Does             │ Example
────────────────────────┼──────────────────────────┼──────────────────────
string.length(s)        │ Count characters         │ length("hi") → 2
string.uppercase(s)     │ Convert to uppercase     │ uppercase("hi") → "HI"
string.lowercase(s)     │ Convert to lowercase     │ lowercase("HI") → "hi"
string.trim(s)          │ Remove leading/trailing  │ trim("  hi  ") → "hi"
                        │ whitespace               │
string.trim_start(s)    │ Remove leading spaces    │ trim_start("  hi") → "hi"
string.trim_end(s)      │ Remove trailing spaces   │ trim_end("hi  ") → "hi"
string.contains(s, sub) │ Check if substring exists│ contains("gleam","lea") → True
string.starts_with(s,p) │ Check prefix             │ starts_with("gleam","gl") → True
string.ends_with(s, p)  │ Check suffix             │ ends_with("gleam","am") → True
string.split(s, sep)    │ Split into a list        │ split("a,b,c", ",") → ["a","b","c"]
string.join(list, sep)  │ Join list into string    │ join(["a","b"], "-") → "a-b"
string.replace(s,f,r)   │ Replace occurrences      │ replace("cat","c","b") → "bat"
string.reverse(s)       │ Reverse characters       │ reverse("gleam") → "maelg"
string.slice(s, i, len) │ Extract substring        │ slice("gleam",0,3) → "gle"

Examples in Code

import gleam/string
import gleam/io

pub fn main() {
  let raw = "  Hello, Gleam!  "

  raw
  |> string.trim
  |> string.uppercase
  |> io.println
  // Output: HELLO, GLEAM!

  let csv = "apple,banana,cherry"
  let fruits = string.split(csv, ",")
  io.debug(fruits)
  // Output: ["apple", "banana", "cherry"]
}

String Interpolation with string.concat

Gleam does not support template literals like JavaScript's backtick syntax. Build dynamic strings by concatenating or using string.concat:

import gleam/string
import gleam/int

let name = "Dev"
let score = 95

let message = string.concat(["Player ", name, " scored ", int.to_string(score), " points!"])
// "Player Dev scored 95 points!"

string.concat takes a list of strings and joins them all — no separator between parts.

Checking String Contents

import gleam/string

let email = "user@example.com"

let has_at = string.contains(email, "@")     // True
let is_empty = string.is_empty(email)        // False
let starts = string.starts_with(email, "user")  // True

Visualizing contains()
──────────────────────────────────────────────
email = "user@example.com"
                ↑
  Looking for "@" inside the string...
  Found it at position 4 → returns True

Slicing Strings

Extract a portion of a string with string.slice:

import gleam/string

let word = "programming"
//          0123456789...

let first_four = string.slice(word, 0, 4)   // "prog"
let middle = string.slice(word, 4, 3)       // "ram"

Slice Diagram: string.slice("programming", 0, 4)
──────────────────────────────────────────────────
p  r  o  g  r  a  m  m  i  n  g
0  1  2  3  4  5  6  7  8  9  10
└─────────┘
 start=0, length=4 → "prog"

Splitting and Joining

import gleam/string

// Split a sentence into words
let sentence = "the quick brown fox"
let words = string.split(sentence, " ")
// ["the", "quick", "brown", "fox"]

// Join them back with a dash
let dashed = string.join(words, "-")
// "the-quick-brown-fox"

Split → Transform → Join Pattern
──────────────────────────────────────────────────
"the quick brown fox"
         ↓ split(" ")
["the", "quick", "brown", "fox"]
         ↓ join("-")
"the-quick-brown-fox"

Converting to and from String

import gleam/int
import gleam/float

// Number to String
let n = int.to_string(42)        // "42"
let f = float.to_string(3.14)    // "3.14"

// String to Number (returns Result type)
let parsed_int = int.parse("123")    // Ok(123)
let bad_parse  = int.parse("hello")  // Error(Nil)

int.parse returns a Result because parsing can fail — the string might not be a valid number. The Result type forces you to handle both cases. You learn about Result in detail in a later topic.

String Comparison

Use == and != to compare strings:

let a = "gleam"
let b = "gleam"
let c = "elixir"

let same = a == b      // True
let different = a != c // True

Gleam compares strings by their content, character by character. Case matters: "Gleam" == "gleam" is False. Use string.lowercase on both strings before comparing if you want case-insensitive equality.

Practical Example — Name Formatter

import gleam/string
import gleam/io

pub fn format_name(first: String, last: String) -> String {
  let clean_first = first |> string.trim |> string.lowercase
  let clean_last  = last  |> string.trim |> string.lowercase

  let cap_first = string.uppercase(string.slice(clean_first, 0, 1))
                  <> string.slice(clean_first, 1, string.length(clean_first) - 1)

  let cap_last = string.uppercase(string.slice(clean_last, 0, 1))
                 <> string.slice(clean_last, 1, string.length(clean_last) - 1)

  cap_first <> " " <> cap_last
}

pub fn main() {
  io.println(format_name("  priya  ", "SHARMA"))
  // Output: Priya Sharma
}

Key Points


String Essentials
──────────────────────────────────────────────────
1. Always wrapped in double quotes
2. UTF-8 encoded — supports all languages + emoji
3. Immutable — string functions return new strings
4. Join with <> operator
5. Use gleam/string module for all operations
6. No built-in template literals — use string.concat
7. Parsing numbers from strings returns a Result type

Gleam's string functions are pure — they return new strings instead of modifying existing ones. This makes your code predictable: a string you pass into a function never changes, no matter what happens inside that function.

Leave a Comment

Your email address will not be published. Required fields are marked *