Appearance
Binaries, strings, and charlists
Source: Elixir guide, Binaries, strings, and charlists.
A string is a binary, a binary is a bitstring, and a charlist is a list. This chapter sorts out which is which.
Code points and UTF-8
Unicode gives every character a number, its code point. ?a is 97, ?ł is 322. "a" writes a character by its hex code point.
A code point is what is stored. An encoding is how. Elixir strings are UTF-8, a variable-width encoding that uses 1 to 4 bytes per code point.
elixir
"héllo" |> String.length() #=> 5
"héllo" |> byte_size() #=> 6
"hełło" <> <<0>>
#=> <<104, 101, 197, 130, 197, 130, 111, 0>> (the exact bytes)A grapheme is what a reader sees as one character. It can be several code points: the woman firefighter emoji is woman + zero-width joiner + fire engine. String.codepoints/1 returns three, String.graphemes/1 and String.length/1 see one.
Bitstrings and binaries
<<>> builds a bitstring, a contiguous run of bits. Each entry is 8 bits unless you say otherwise with ::n.
elixir
<<42>> == <<42::8>> #=> true
<<0::1, 0::1, 1::1, 1::1>> == <<3::4>> #=> true
<<1>> == <<257>> #=> true (257 doesn't fit in 8 bits, it's truncated)A binary is a bitstring whose bit count is divisible by 8.
elixir
is_bitstring(<<3::4>>) #=> true
is_binary(<<3::4>>) #=> false
is_binary(<<0, 255, 42>>) #=> trueYou can pattern match on binaries. Each entry matches exactly one byte unless you add a modifier:
elixir
<<0, 1, x>> = <<0, 1, 2>> # x = 2
<<0, 1, x>> = <<0, 1, 2, 3>> #=> ** (MatchError)
<<0, 1, x::binary>> = <<0, 1, 2, 3>> # x = <<2, 3>>
<<head::binary-size(2), rest::binary>> = <<0, 1, 2, 3>>Strings are binaries
A string is a UTF-8 binary. <> is really binary concatenation, so <<0, 1>> <> <<2, 3>> works. Not every binary is a valid string: String.valid?(<<239, 191, 19>>) is false.
Matching a string works on bytes, not characters. Use the utf8 modifier to match a whole character:
elixir
<<x, rest::binary>> = "über"
x == ?ü #=> false (x is the first byte of ü)
<<x::utf8, rest::binary>> = "über"
x == ?ü #=> true rest is "ber"Charlists
A charlist is a list of integers that are valid code points. You mostly meet them when calling older Erlang libraries that don't take binaries.
elixir
~c"hello" #=> ~c"hello"
[?h, ?e, ?l, ?l, ?o] #=> ~c"hello"
~c"hełło" #=> [104, 101, 322, 322, 111]IEx prints a list as ~c"…" only when every number is in the ASCII range, so [99, 97, 116] shows as ~c"cat". inspect(list, charlists: :as_list) forces the list form. to_string/1 and to_charlist/1 convert, and to_string/1 also takes atoms and numbers.
Strings use <>, charlists (being lists) use ++. Mixing them fails: ~c"this " <> ~c"fails" raises ArgumentError.