Strings, Binaries, Charlists & Unicode

Modifiers: integer, float, bits/bitstring, binary/bytes, utf8/utf16/utf32, signed/unsigned, big/little/native, size(n), unit(n).

16.1 Strings are UTF-8 binaries

s = "héllo"
is_binary(s)               # true
byte_size(s)               # 6
String.length(s)           # 5 graphemes
String.codepoints("é")     # ["é"]
String.graphemes("🇳🇴")    # ["🇳🇴"] (one grapheme, two codepoints)
<<head::utf8, _::binary>> = "élan"   # head = 233
?é                         # 233
"é" == "é"       # true — \u escape for a code point

16.2 The String module

String.upcase("abc"), String.downcase("ABC"), String.capitalize("elixir")
String.trim("  hi  "), String.trim_leading, String.trim_trailing
String.split("a,b,,c", ",")                    # ["a", "b", "", "c"]
String.split("a,b,,c", ",", trim: true)        # ["a", "b", "c"]
String.split("hello world")                    # split on whitespace
String.replace("hello", "l", "L")              # "heLLo"
String.replace("hello", "l", "L", global: false)
String.contains?("elixir", "xir")
String.starts_with?("elixir", "eli"), String.ends_with?("elixir", ["ir", "ang"])
String.slice("elixir", 1..3)                   # "lix"
String.at("elixir", 0)                         # "e"
String.reverse("abc")
String.pad_leading("7", 3, "0")                # "007"
String.duplicate("ab", 3)
String.to_integer("42"), String.to_float("3.5")
String.to_atom("ok"), String.to_existing_atom("ok")
String.myers_difference, String.jaro_distance("dwayne", "duane")
String.normalize("é", :nfd)
String.valid?(<<0xFF>>)                        # false
String.chunk, String.splitter, String.split_at("hello", 2)

16.3 Binaries & bitstrings

Modifiers: integer, float, bits/bitstring, binary/bytes, utf8/utf16/utf32, signed/unsigned, big/little/native, size(n), unit(n).

<<1, 2, 3>>
<<0::1, 1::1>>                   # bitstring of 2 bits
<<255::16>>                      # <<0, 255>>
<<x::float-32>> = <<1.5::float-32>>
<<len::16, payload::binary-size(len), rest::binary>> = packet
<<a::little-integer-32>> = <<1, 0, 0, 0>>       # a = 1
# Parse a PNG header
<<0x89, "PNG", 0x0D, 0x0A, 0x1A, 0x0A, _::binary>> = File.read!("img.png")

16.4 Charlists

Mainly used when calling Erlang functions that expect strings as lists: :string.uppercase(~c"abc").

~c"hello"                 # [104, 101, 108, 108, 111]
to_charlist("hi"), to_string(~c"hi"), List.to_string([104, 105])

16.5 IO data & interpolation

iodata = nested lists of binaries/bytes; avoids copying when writing output:

Interpolation calls String.Chars.to_string/1: "#{1.5} #{:atom} #{[1, 2]}". Use inspect/1 for debugging any term.

IO.puts(["Hello", ?\s, ["wor", "ld"]])
IO.iodata_to_binary(["a", ["b"]])
IO.iodata_length(["ab", "c"])