Lavorare con i dati binari può essere complicato, perciò Gleam fornisce un tipo BitArray e una sintassi dedicata per costruire dati binari e fare pattern matching su di essi.
I letterali di array di bit si definiscono con la sintassi <<>>. Quando definisci un letterale di array di bit, lo fai per segmenti. Ogni segmento ha un valore ed un'annotazione, separati da :. L'annotazione specifica quanti bit verranno usati per codificare il valore e può essere omessa del tutto, nel qual caso il valore predefinito è un intero a 8 bit.
// 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>>
Specificare il tipo come :1 è una scorciatoia per scrivere :size(1). Devi usare la sintassi più lunga se la dimensione in bit proviene da una variabile.
let segment_size = 1
<<0:size(segment_size), 1:size(segment_size), 0:size(segment_size)>>
Quando scriviamo letterali interi binari, possiamo scriverli direttamente in notazione in base 2 anteponendo 0b al letterale. Tieni presente che verranno mostrati come numeri decimali quando vengono stampati nei test o nel tuo programma.
<<0b1011:4>> == <<11:4>>
// -> True
Se il valore del segmento supera la capacità del tipo del segmento, viene troncato da sinistra.
<<0b1011:3>> == <<0b0011:3>>
// -> True
Puoi sia aggiungere in testa sia aggiungere in coda a un array di bit esistente usando la sintassi degli array di bit. Per l'array di bit esistente bisogna usare l'annotazione :bits.
let value = <<0b110:3, 0b001:3>>
let new_value = <<0b011:3, value:bits, 0b000:3>>
// -> <<120, 8:size(4)>>
Possiamo concatenare con questa sintassi gli array di bit salvati nelle variabili. L'annotazione :bits va usata quando si concatenano due array di bit di dimensioni variabili.
let first = <<0b110:3>>
let second = <<0b001:3>>
let concatenated = <<first:bits, second:bits>>
// -> <<49:size(6)>>
Puoi fare pattern matching anche per ottenere valori dall'array di bit. Devi conoscere il numero di bit di ogni frammento che vuoi catturare, con un'eccezione: l'annotazione :bits può essere usata per fare pattern matching su un array di bit di dimensione sconosciuta, ma solo per l'ultimo frammento.
let assert <<value:4, rest:bits>> = <<0b01101001:8>>
value == 0b0110
// -> true
Gli array di bit potrebbero essere stampati in un formato diverso da quello usato per crearli. Questo crea spesso confusione quando si imparano gli array di bit.
Per impostazione predefinita, gli array di bit vengono mostrati in frammenti da 8 bit (un byte), anche se li hai creati con frammenti di dimensioni diverse.
<<2011:11>>
// -> <<251, 3:size(3)>>
Se crei un array di bit che rappresenta una stringa stampabile codificata in UTF-8, può essere mostrato come stringa usando echo keyword quando il target è Erlang. Questo è dovuto a un dettaglio implementativo di come Gleam rappresenta le stringhe al suo interno.
<<>>
// -> ""
<<65, 66, 67>>
// -> "ABC"