Trabalhar com dados binários pode ser complicado, por isso o Gleam fornece um tipo BitArray e a sintaxe associada para construir e fazer correspondência de padrões em dados binários.
Os literais de arrays de bits são definidos com a sintaxe <<>>. Ao definir um literal de array de bits, este é definido em segmentos. Cada segmento tem um valor e uma anotação, separados por :. A anotação especifica quantos bits serão usados para codificar o valor e pode ser omitida por completo, o que faz com que o valor predefinido seja um inteiro de 8 bits.
// This defines a bit array with three segments of a single bit each
<<0:1, 1:1, 0:1>>
// This defines a bit array with three segments of 8 bits each
<<0, 1, 0>>
Especificar o tipo como :1 é uma forma abreviada de escrever :size(1). Tens de usar a sintaxe mais longa se o tamanho em bits vier de uma variável.
let segment_size = 1
<<0:size(segment_size), 1:size(segment_size), 0:size(segment_size)>>
Ao escrever literais inteiros binários, podemos escrevê-los diretamente em notação de base 2, prefixando o literal com 0b. Repara que serão apresentados como números decimais quando impressos nos testes ou no teu programa.
<<0b1011:4>> == <<11:4>>
// -> True
Se o valor do segmento exceder a capacidade do tipo do segmento, será truncado a partir da esquerda.
<<0b1011:3>> == <<0b0011:3>>
// -> True
Podes adicionar tanto ao início como ao fim de um array de bits existente usando a sintaxe de arrays de bits. A anotação :bits tem de ser usada para o array de bits existente.
let value = <<0b110:3, 0b001:3>>
let new_value = <<0b011:3, value:bits, 0b000:3>>
// -> <<120, 8:size(4)>>
Podemos concatenar arrays de bits guardados em variáveis usando a sintaxe. A anotação :bits tem de ser usada ao concatenar dois arrays de bits de tamanhos variáveis.
let first = <<0b110:3>>
let second = <<0b001:3>>
let concatenated = <<first:bits, second:bits>>
// -> <<49:size(6)>>
Também é possível fazer correspondência de padrões para obter valores do array de bits. Tens de saber o número de bits de cada fragmento que queres capturar, com uma exceção: a anotação :bits pode ser usada para fazer correspondência de padrões num array de bits de tamanho desconhecido, mas só pode ser usada para o último fragmento.
let assert <<value:4, rest:bits>> = <<0b01101001:8>>
value == 0b0110
// -> true
Os arrays de bits podem ser impressos num formato diferente do formato usado para os criar. Isto causa frequentemente confusão quando se está a aprender arrays de bits.
Por predefinição, os arrays de bits são apresentados em fragmentos de 8 bits (um byte), mesmo que os tenhas criado com fragmentos de um tamanho diferente.
<<2011:11>>
// -> <<251, 3:size(3)>>
Se criares um array de bits que representa uma string imprimível codificada em UTF-8, pode ser apresentado como string usando a echo keyword quando o alvo é Erlang. Isto deve-se a um detalhe de implementação da forma como o Gleam representa strings internamente.
<<>>
// -> ""
<<65, 66, 67>>
// -> "ABC"