← Code Compare

Strings

From name = "Ada" and year = 1815, build and print Hello, Ada! (1815), then upper-case the name to print ADA. The big watch-point is what a "string" even is: classic Erlang strings are lists of character codepoints ("Ada" is really [65,100,97]), while Elixir, Gleam, and modern Erlang prefer UTF-8 binaries. Notice too how each language interpolates or formats - Erlang/LFE io_lib/io:format with ~s/~p, Elixir #{...}, Gleam explicit <> concatenation with int.to_string, and Lua string.format - and which upper-casing function is Unicode-aware versus Latin-1 only.

Show: ErlangElixirGleamLFELuerl
Erlang
-module(strings).
-export([demo/0]).

demo() ->
    Name = "Ada",          % a char list: [65, 100, 97]
    Year = 1815,
    Line = io_lib:format("Hello, ~s! (~p)", [Name, Year]),
    io:format("~s~n", [Line]),
    %% string:uppercase/1 is Unicode-aware (OTP 20+)
    io:format("~s~n", [string:uppercase(Name)]).
%% => Hello, Ada! (1815)
%% => ADA

A double-quoted "Ada" is a char list (a list of integer codepoints), formatted via ~s. io_lib:format/2 builds an iolist you can reuse, and string:uppercase/1 upper-cases in a Unicode-aware way. Modern code often prefers <<"Ada">> binaries instead.

Elixir
name = "Ada"        # a UTF-8 binary, not a char list
year = 1815

IO.puts("Hello, #{name}! (#{year})")
IO.puts(String.upcase(name))
# => Hello, Ada! (1815)
# => ADA

Elixir strings are UTF-8 binaries, and #{...} interpolates any value (calling to_string/1 for you). String.upcase/1 is fully Unicode-aware. A char list, if you ever need one, is written with the ~c"Ada" sigil.

Gleam
import gleam/io
import gleam/int
import gleam/string

pub fn main() {
  let name = "Ada"
  let year = 1815

  io.println("Hello, " <> name <> "! (" <> int.to_string(year) <> ")")
  io.println(string.uppercase(name))
}
// => Hello, Ada! (1815)
// => ADA

Gleam has no string interpolation: you join pieces with the <> operator, and the compiler forces int.to_string(year) because an Int is not a String. string.uppercase from gleam/string is Unicode-aware.

LFE
(defmodule strings
  (export (demo 0)))

(defun demo ()
  (let ((name "Ada")        ; a char list, just like Erlang
        (year 1815))
    (io:format "Hello, ~s! (~p)~n" (list name year))
    (io:format "~s~n" (list (string:uppercase name)))))
;; => Hello, Ada! (1815)
;; => ADA

LFE shares Erlang's runtime, so "Ada" is the same char list and io:format with ~s/~p does the formatting. It calls the very same string:uppercase/1 BEAM function, written as an S-expression.

Luerl
local name = "Ada"
local year = 1815

print(string.format("Hello, %s! (%d)", name, year))
print(string.upper(name))
-- => Hello, Ada! (1815)
-- => ADA

Standard Lua strings are immutable byte sequences. string.format with %s/%d builds the line, and string.upper upper-cases - but only ASCII/Latin-1, since Lua's core string library is byte-oriented and not Unicode-aware.