Asier Azkuenaga
Asier Azkuenaga

Reputation: 1189

Binary comprehension on Elixir

Is it possible and if so, how could I use binary comprehension on Elixir? I can do it on Erlang like so:

[One || <<One, _rest:3/binary>> <= <<1,2,3,4>>].

Upvotes: 4

Views: 1435

Answers (2)

zxq9
zxq9

Reputation: 13154

What in Erlang is:

1> [Red || <<Red:2/binary, _Blue:2/binary>> <= <<1, 2, 3, 4, 5, 6, 7, 8>> ].
[<<1,2>>,<<5,6>>] 

In Elixir is:

iex(1)> for <<red::8, green::8, blue::16 <- <<1, 2, 3, 4, 5, 6, 7, 8>> >>, do: <<red, green>>
[<<1, 2>>, <<5, 6>>]

Note that the Elixir above is explicitly declaring sizes in bits, whereas the Erlang is using a type for make the calculation chop off a size in bytes. There is probably a cleaner way to do that in Elixir (at least I hope there is) and I might even hunt around for it -- but most of the time when I want to do this stuff extensively I stick to Erlang just for readability/universality.

Addendum

@aronisstav asked an interesting question: "Shouldn't there be a part matching the green pattern in the Erlang code?"

The answer is that there would be a Green variable in Erlang were that code to deal with bitstrings instead of binaries. Erlang's bit syntax provides ways to indicate a few arbitrary binary types which correspond to default sizes. Above I matched Red:2/binary which means I want to match a sequence of 2 bytes, and this is how we get the result [<<1,2>><<5,6>>]: two sequences of two bytes.

An Erlang example that is exactly equivalent to the Elixir code above would be:

[<<Red/bitstring, Green/bitstring>>
 || <<Red:8/bitstring, Green:8/bitstring, _Blue:2/binary>>
    <= <<1, 2, 3, 4, 5, 6, 7, 8>> ].

But that is just silly to do, as Erlang's syntax for bytes is much more concise.

Upvotes: 4

Asier Azkuenaga
Asier Azkuenaga

Reputation: 1189

I found the solution in the documentation:

for << one, _rest :: binary - size(3) <- <<1,2,3,4>> >>, do: one

Upvotes: 1

Related Questions