I am trying to build up a bitstring from an ascii string of 0’s and 1’s.
So the idea is I am receiving an ascii string and then a single character ?1 or ?0.
But no matter how many type annotations I give it, I keep getting an argument error from Kernel.<> I guess because it wants a binary.
What is the proper way to go about this?
defmodule MakeBits do
@spec char2bit(number) :: bitstring
def char2bit(48), do: <<0::1>>
def char2bit(49), do: <<1::1>>
def append_ascii(ascii_bitstring, ascii_bit) do
bitstring = Enum.reduce(String.to_charlist(ascii_bitstring), <<>>, fn x, acc -> acc <> char2bit(x) end)
bitstring # TODO append ascii_bit
end
def test() do
incoming_ascii_string = "10101"
append_ascii(incoming_ascii_string, '1') == <<1::1, 0::1, 1::1, 0::1, 1::1, 1::1>>
end
end
You can concatenate bitstrings like this: <<a::bitstring, b::bitstring>>
This works:
defmodule MakeBits do
@spec char2bit(number) :: bitstring
def char2bit(48), do: <<0::1>>
def char2bit(49), do: <<1::1>>
def append_ascii(ascii_bitstring, ascii_bit) do
bitstring =
Enum.reduce(String.to_charlist(ascii_bitstring), <<>>, fn x, acc ->
<<acc::bitstring, char2bit(x)::bitstring>>
end)
# TODO append ascii_bit
end
def test() do
incoming_ascii_string = "10101"
# Fixed order of match and using = instead of == so that test works
<<1::1, 0::1, 1::1, 0::1, 1::1, 1::1>> = append_ascii(incoming_ascii_string, ?1)
end
end
MakeBits.test()
def append_ascii(ascii_bitstring, ascii_bit) do
codepoints = String.to_charlist(ascii_bitstring) ++ ascii_bit
for cp <- codepoints, do: char2bit(cp), into: <<>>
end
It passes your original test, but I think @Nicd did the right thing by fixing your test to accept a single codepoint as you said, rather than a single-element charlist as you actually wrote in your test.
I also rewrote the reduce into a comprehension with a binary collector.
You could also do it with bitstring generators, but you need to change the char2bit function too:
def char2bit(?0), do: 0
def char2bit(?1), do: 1
def append_ascii(ascii_bitstring, [ascii_bit]) do
bitstring = for <<cp <- ascii_bitstring>>, do: <<char2bit(cp)::1>>, into: <<>>
<<bitstring::bitstring, char2bit(ascii_bit)::1>>
end