2012年1月17日火曜日

Erlang queueモジュールによるstackモジュール作成

stackモジュールがないので、作ってみた。突貫で。
コンパイルとおしただけ。

1番下にある追記参照。

【ソース】


-module(stack).
-ifdef(debug).
-include_lib("eunit/include/eunit.hrl").
-endif.
-export([new/0,
        is_stack/1,
        is_empty/1,
        len/1,
        push/2,
        pop/1,
        from_list/1,
        to_list/1,
        reverse/1
        ]).
% -----
% stack of queue module
% -----
% stack()
-record( stack, { stk=undefined } ).
-define( __q, queue ).
-define( __is_q( X ), ?__q:is_queue( X ) ).
-define( __proc_q( X ), ( begin
                            case ?__is_q( Stack ) of
                                true ->
                                    ?__q:X( Stack );
                                _ ->
                                    error
                            end
                        end )
       ).
% @spec new() -> stack()
new() ->
    #stack{ stk=queue:new() }.

% @spec is_stack(Term::term()) -> boolean
is_stack( #stack{ stk=Stack } ) ->
    ?__is_q( Stack );
is_stack( _ ) ->
    error.

% @spec is_empty(S :: stack()) -> boolean | error
%is_empty(Stack) ->
is_empty( #stack{ stk=Stack } ) ->
    ?__proc_q( is_empty );

is_empty( _ ) ->
    error.

% @spec len( stack() ) -> integer() >= 0 | error
len( #stack{ stk=Stack } ) ->
    ?__proc_q( len );
len( _ ) ->
    error.

% @spec push( term(), stack() ) -> stack() | error
push( Item, #stack{ stk=Stack } ) ->
    case ?__is_q( Stack ) of
        true ->
            Stack1 = queue:in( Item, Stack ),
            #stack{ stk=Stack1 };
        _ ->
            error
    end;
push( _, _ ) ->
    error.

% @spec pop( stack() ) -> {{value, term()}, stack()} | {empty, stack()} | error
pop( #stack{ stk=Stack } ) ->
    Stack1 = ?__proc_q( out_r ),
    case Stack1 of
        { { value, Value }, Queue } ->
            { {value, Value}, #stack{ stk=Queue } };
        { empty, Queue } ->
            { empty, #stack{ stk=Queue } };
        _ ->
            error
    end;
pop( _ ) ->
    error.

% @spec from_list( list() ) -> stack()
from_list( List ) when is_list( List ) ->
        Stack = queue:from_list( List ),
        #stack{ stk=Stack };
from_list( _ ) ->
        error.

% @spec to_list( stack() ) -> list()
to_list( #stack{ stk=Stack } ) ->
    case ?__is_q( Stack ) of
        true ->
            queue:to_list( Stack );
        _ ->
            error
    end;
to_list( _ ) ->
    error.

%@spec reverse( stack() ) -> stack() | error
reverse( #stack{ stk=Stack } ) ->
    Stack1 = ?__proc_q( reverse ),
    case Stack1 of
        error ->
            error;
        _ ->
            { stack, Stack1 }
    end;
reverse( _ ) ->
    error.