最近比較忙, 一來是在努力學習erlang, 二來是戀戀不捨那幾個開源的小專案,三來是熟悉親愛的r13a...
加上令人頭疼的公司的事情, 導致我很忙... 哎...
為了保持部落格的新鮮度, 就貼一點充數的資料吧..呵呵...
在我前段時間搞的乙個開源的mapreduce小框架中, 對於map, reduce資料流的讀取, 我抽象出乙個迭代器, 進行資料的讀取.
這樣我的資料無論來自local disk, 來自memory, 來時nfs都一視同仁...
在寫乙個module之前,我先想象其介面及用法:
%%% usage:
%%% iter = make_iter(prev_fun, next_fun, state),
%%% = next(iter),
%%% = next(iter2),
%%% = prev(iter3).
我們首先通過呼叫make_iter/3 構建乙個迭代器, 第乙個引數是乙個函式用來獲取前一條記錄, 第二個引數用來獲取下一條
記錄. state是乙個內部狀態資訊, 用來儲存當前的狀態.
構造好iter後, 我們可以通過呼叫prev/1, next/1 來遍歷這個iter.
這個實現,有點oo的感覺在裡面, iter可以理解為乙個物件,其state為內部資料, prev_fun, next_fun為對應的方法.
為了讓我們的iter模組更豐富,我們仿照lists module, 加入了foldl/3 和 foldr/3 兩個函式.
當然還可以讓這個iter功能更強大,比如是否可以迴圈迭代?是否可以雙向或單向迭代?等等.有興趣朋友可以實現哦.
好了,貼上**:
-module(heng_iter).
-author('[email protected]').
-vsn('0.1').
-include("heng_master.hrl").
-export([make_iter/3]).
-export([next/1, prev/1]).
-export([foldl/3, foldr/3]).
-record(iter,
).%% @doc get the next item
next(#iter) ->
;next(iter = #iter) ->
case next(state) of
nil -> % to the end
; ->
, iter#iter}
end.
%% @doc get the item in the backward
prev(#iter) ->
;prev(iter = #iter) ->
case prev(state) of
nil -> % to the end
; ->
, iter#iter}
end.
%-spec foldl(fun :: fun(), acc :: term(), iter :: iter()) ->
% term().
foldl(fun, acc, iter) when is_function(fun, 2) ->
= next(iter),
foldl0(fun, acc, v, iter2).
foldl0(_fun, acc, nil, _iter) ->
acc;
foldl0(fun, acc, , iter) ->
acc2 = fun(v, acc),
= next(iter),
foldl0(fun, acc2, v2, iter2).
foldr(fun, acc, iter) when is_function(fun, 2) ->
= prev(iter),
foldr0(fun, acc, v, iter2).
foldr0(_fun, acc, nil, _iter) ->
acc;
foldr0(fun, acc, , iter) ->
acc2 = fun(v, acc),
= prev(iter),
foldr0(fun, acc2, v2, iter2).
%% @doc 'fward' equal 'forward' , 'bid' equal 'bidirectional'
make_iter(next, prev, state)
when is_function(next) andalso is_function(prev)
%andalso ((type =:= 'normal') or (type =:= 'cyclic'))
->
#iter.
最後是乙個小例子, 我們定義乙個迭代器,用來訪問list, 當然這個做法似乎有點多此一舉..
(這段**摘自 iter 模組中的測試** )
%% @doc some test
basic_test_() ->
data = ["begin", "one", "two", "there", "four", "end"],
expr1 = "begin one two there four end",
expr2 = "end four three two one begin",
%% 定義乙個迭代器, 其呼叫listnext/1 獲取下一條記錄, 呼叫listprev/1 獲取上一條記錄, state為乙個tuple
%% 分別儲存:資料的begin, last, length 和具體的資料(也就是list)
iter = make_iter(fun listnext/1, fun listprev/1, ),
r =
?module:foldl(fun(str, acc) ->
[str, $ | acc]
end,
,iter),
str = lists:flatten(lists:reverse(r)), % str 為 expr1
iter2 = make_iter(fun listnext/1, fun listprev/1, ),
r2 =
?module:foldr(fun(e, acc) ->
[e, $ | acc]
end,
,iter2),
str2 = lists:flatten(lists:reverse(r2)), % str 為 expr2
[?_assert(str = expr1),
?_assert(str2 = expr2)
].
%% 用來獲取下一條記錄
listnext() ->
nil;
listnext() ->
pos2 = pos + 1,
v = lists:nth(pos2, data),
}. %% 用來獲取前一條記錄
listprev() ->
nil;
listprev() ->
nil;
listprev() ->
pos2 = pos - 1,
v = lists:nth(pos2, data),
}.
好了就是這些, 有了這個module, 在mapreduce框架中,使用者可以自定義各種的iter 實現, map, reduce會依據使用者的iter
進行具體的資料讀取,然後進行處理..
詳細的**, 請參考此處:
[url]
學習STL,實現乙個單鏈表的迭代器
stl原始碼剖析中,空間配置器和迭代器屬於比較晦澀難懂的兩章,這裡學習了stl迭代器後也嘗試自己寫乙個迭代器,實現單鏈表的迭代器,實現不難,可以說是乙個玩具而已,但是能夠幫助我們理解stl迭代器的基本原理。宣告 templateclass listiterator templateclass lin...
Erlang 建立乙個簡單的TCP伺服器
一 建立 tcpserver.erl module tcpserver export start 0 start 建立乙個埠2345用於監聽來自客戶端的請求,是資訊表頭用4位元組表示長度,需要與客戶端一致 gen tcp listen 2345,binary,開始接受乙個請求 gen tcp acc...
Erlang之乙個簡單的TCP伺服器
簡單tcp伺服器 module my socket server export start 0,loop 1 start gen tcp listen 2345,binary,自定義打包規則,生成乙個監聽2345埠的socket gen tcp accept listen 生存乙個新的socket ...