implementation of the splitting binary function of erlang

I’m new in the Erlang world. I’m trying to implement the function split_binary. The function takes as input (list, index) and it splits the list in two lists according to the index.

According to the erlang docs for split_binary/2, the two arguments are a binary, which is not a list, and the number of bytes where you want to split the binary.

First, you need to have a basic understanding of what a binary is. A binary is a sequence of bytes, where each byte is 8 bits representing some integer, e.g.

0010 0001

which is 33. Here is an example of a binary:

<<1, 2, 3>>

When you don’t specify a size for each integer, by default each integer will occupy one byte. If you wanted the 2 to occupy two bytes instead, i.e. 0000 0000 0000 0010, which is 16 bits, then you could write:

<<1, 2:16, 3>>

which the shell would display as:

 <<1,0,2,3>>

Huh? Where did that 0 come from? The shell displays a binary byte by byte, and the first byte of the integer 0000 0000 0000 0010 is 0000 0000, which is 0.

Next, you can step through a binary just like you can for a list, extracting any number of bits at a time from the front of the binary. It so happens that split_binary/2 extracts 8 bits, or 1 byte, at a time from the head of the binary.

There are a couple of tricks to learning how to step through a binary:

  1. For lists, [] means an empty list, and for binaries <<>> means an empty binary.

  2. For lists you write [Head|Tail] to extract the head of the list, and for binaries you write <<Bits:3, Rest/binary>> to extract 3 bits from the front of the binary. In your case, you need to extract 8 bits from the front of the binary.

Here is an example of what you can do:

-module(a).
-compile(export_all).

split_b(Bin, N) ->
    split_b(Bin, N, _Acc = <<>>).

split_b(     Bin,               _N = 0, Acc) -> [Acc, Bin];
split_b(<<Bits:8, Rest/binary>>, N,     Acc) ->
    split_b(Rest, N-1, <<Acc/binary, Bits>>).

In the shell:

40> c(a).
a.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,a}

41> a:split_b(<<5,6,7>>, 1).
[<<5>>,<<6,7>>]

42> a:split_b(<<5,6,7>>, 2).
[<<5,6>>,<<7>>]

Note that when constructing a binary one of the segments of the binary can be another binary:

23> Bin = <<1, 2, 3>>.        
<<1,2,3>>

24> Acc = <<Bin/binary, 4>>.
<<1,2,3,4>>

If you are actually trying to implement lists:split/2, you can do this:

-module(a).
-compile(export_all).

split_l(N, List) -> 
    split_l(N, List, _Acc=[]).

split_l(_N=0, List, Acc) ->
    [lists:reverse(Acc), List];
split_l(N, [H|T], Acc) -> 
    split_l(N-1, T, [H|Acc]).

In the shell:

2> c(a).
a.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,a}

3> a:split_l(1, [10, 20, 30]).
["\n",[20,30]]

4> shell:strings(false).
true

5> a:split_l(1, [10, 20, 30]).
[[10],[20,30]]

6> a:split_l(2, [10, 20, 30]).
[[10,20],[30]]

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top