Iolist 和 Bitstring
像列表一樣, iolist 和 bitstring 最簡單的函式是:
-spec loop(iolist()) -> ok | {ok, iolist} .
loop(<<>>) ->
ok;
loop(<<Head, Tail/bitstring>>) ->
loop(Tail);
loop(<<Rest/bitstring>>) ->
{ok, Rest}
你可以這樣稱呼它:
loop(<<"abc">>).
這裡的遞迴函式擴充套件:
loop(<<"a"/bitstring, "bc"/bitstring>>) ->
loop(<<"b"/bitstring, "c"/bitstring>>) ->
loop(<<"c"/bitstring>>) ->
loop(<<>>) ->
ok.
可變二進位制大小的遞迴函式
此程式碼採用 bitstring 並動態定義它的二進位制大小。因此,如果我們設定 4
的大小,每個 4
位,資料將匹配。這個迴圈沒有什麼有趣的,它只是我們的支柱。
loop(Bitstring, Size)
when is_bitstring(Bitstring), is_integer(Size) ->
case Bitstring of
<<>> ->
ok;
<<Head:Size/bitstring,Tail/bitstring>> ->
loop(Tail, Size);
<<Rest/bitstring>> ->
{ok, Rest}
end.
你可以這樣稱呼它:
loop(<<"abc">>, 4).
這裡的遞迴函式擴充套件:
loop(<<6:4/bitstring, 22, 38, 3:4>>, 4) ->
loop(<<1:4/bitstring, "bc">>, 4) ->
loop(<<6:4/bitstring, 38,3:4>>, 4) ->
loop(<<2:4/bitstring, "c">>, 4) ->
loop(<<6:4/bitstring, 3:4>>, 4) ->
loop(<<3:4/bitstring>>, 4) ->
loop(<<>>, 4) ->
ok.
我們的位字串分為 7 種模式。為什麼?因為預設情況下,Erlang 使用 8
位的二進位制大小,如果我們將它分成兩個,我們有 4
位。我們的字串是 8*3=24
位。24/4=6
模式。最後的模式是 <<>>
。loop/2
函式被呼叫 7 次。
帶有動作的可變二進位制大小的遞迴函式
現在,我們可以做更多有趣的事情。這個函式還有一個引數,一個匿名函式。每當我們匹配一個模式時,這個模式就會被傳遞給它。
-spec loop(iolist(), integer(), function()) -> ok.
loop(Bitstring, Size, Fun) ->
when is_bitstring(Bitstring), is_integer(Size), is_function(Fun) ->
case Bitstring of
<<>> ->
ok;
<<Head:Size/bitstring,Tail/bitstring>> ->
Fun(Head),
loop(Tail, Size, Fun);
<<Rest/bitstring>> ->
Fun(Rest),
{ok, Rest}
end.
你可以這樣稱呼它:
Fun = fun(X) -> io:format("~p~n", [X]) end.
loop(<<"abc">>, 4, Fun).
這裡的遞迴函式擴充套件:
loop(<<6:4/bitstring, 22, 38, 3:4>>, 4, Fun(<<6:4>>) ->
loop(<<1:4/bitstring, "bc">>, 4, Fun(<<1:4>>)) ->
loop(<<6:4/bitstring, 38,3:4>>, 4, Fun(<<6:4>>)) ->
loop(<<2:4/bitstring, "c">>, 4, Fun(<<2:4>>)) ->
loop(<<6:4/bitstring, 3:4>>, 4, Fun(<<6:4>>) ->
loop(<<3:4/bitstring>>, 4, Fun(<<3:4>>) ->
loop(<<>>, 4) ->
ok.
通過 bitstring 返回修改後的 bitstring 的遞迴函式
這個類似於 lists:map/2
但是對於 bitstring 和 iolist。
% public function (interface).
-spec loop(iolist(), fun()) -> iolist() | {iolist(), iolist()}.
loop(Bitstring, Fun) ->
loop(Bitstring, 8, Fun).
% public function (interface).
-spec loop(iolist(), integer(), fun()) -> iolist() | {iolist(), iolist()}.
loop(Bitstring, Size, Fun) ->
loop(Bitstring, Size, Fun, <<>>)
% private function.
-spec loop(iolist(), integer(), fun(), iolist()) -> iolist() | {iolist(), iolist()}.
loop(<<>>, _, _, Buffer) ->
Buffer;
loop(Bitstring, Size, Fun, Buffer) ->
when is_bitstring(Bitstring), is_integer(Size), is_function(Fun) ->
case Bitstring of
<<>> ->
Buffer;
<<Head:Size/bitstring,Tail/bitstring>> ->
Data = Fun(Head),
BufferReturn = <<Buffer/bitstring, Data/bitstring>>,
loop(Tail, Size, Fun, BufferReturn);
<<Rest/bitstring>> ->
{Buffer, Rest}
end.
這段程式碼看起來更復雜。增加了兩個功能:loop/2
和 loop/3
。這兩個功能是與 loop/4
的簡單介面。
你可以像這樣執行它:
Fun = fun(<<X>>) -> << (X+1) >> end.
loop(<<"abc">>, Fun).
% will return <<"bcd">>
Fun = fun(<<X:4>>) -> << (X+1) >> end.
loop(<<"abc">>, 4, Fun).
% will return <<7,2,7,3,7,4>>
loop(<<"abc">>, 4, Fun, <<>>).
% will return <<7,2,7,3,7,4>>