[newbie] refactor function?
Gaspar Chilingarov
nm@REDACTED
Wed Feb 2 11:44:42 CET 2005
Hi!
Carsten Schultz wrote:
> Hi!
>
> On Tue, Feb 01, 2005 at 01:07:10PM +0400, Gaspar Chilingarov wrote:
>
>>Hello All!
>>
>>what is a correct way of writing following function (initQuota/1) --
>>probably i got problems thinking in a functional way ;) ?
>>
>>i wish to get rid of last two cases.
>>
>>following function just adds to list of tuples with range descriptions
>>initial zero value, which will be changed later in application.
>>
>>-cut-
>>testInitQuota() ->
>> [{ single, "AAA", 0 }] = initQuota( [ { single, "AAA" } ] ),
>> [{ range, "AAA", "BBB", 0 }] =
>> initQuota( [ { range, "AAA", "BBB" } ] ),
>> [{ single, "AAA", 0 },{ range, "AAA", "BBB", 0 }] =
>> initQuota( [ { single, "AAA" },{ range, "AAA", "BBB" } ] ).
>>
>>initQuota([Head | QuotaList]) ->
>> lists:reverse(initQuota(Head, QuotaList, [])).
>>
>>initQuota( { range, Value1, Value2 }, [Head | QuotaList], NewList ) ->
>> initQuota( Head, QuotaList, [ { range, Value1, Value2, 0 } ] ++
>>NewList );
>>initQuota( { single, Value1 }, [Head | QuotaList], NewList ) ->
>> initQuota( Head, QuotaList, [ { single, Value1, 0 } ] ++ NewList );
>>initQuota( { range, Value1, Value2 }, [], NewList ) ->
>> [ { range, Value1, Value2, 0 } ] ++ NewList;
>>initQuota( { single, Value1 }, [], NewList ) ->
>> [ { single, Value1, 0 } ] ++ NewList.
>>-cut-
>
>
> Well I would first write a specification of what the function should
> do, like
>
> initQuota(X) ->
> lists:map(fun({range, Value1, Value2}) ->
> {range, Value1, Value2, 0};
> ({single, Value1}) ->
> {single, Value1}
> end, X).
>
> :-)
>
> If you do not like funs like this, that would have been
>
> initQuota(List) ->
> lists:map(fun initQuotaElement/1, List).
>
> initQuotaElement({range, Value1, Value2}) ->
> {range, Value1, Value2, 0};
> initQuotaElement({single, Value1}) ->
> {single, Value1}.
>
thats ok -- elegant and very short way to write this i need.
> BTW, the problem with your solution seems to be that you are doing to
> pattern matches at once, although they are independent of each other.
> You could have written:
>
> initQuota(Val, List, NewList) ->
> NewVal = case Val of
> {range, Value1, Value2} ->
> {range, Value1, Value2, 0};
> {single, Value1} ->
> {single, Value1, 0}
> end,
> case List of
> [] ->
> [NewVal | NewList];
> [Head | Tail] ->
> initQuota(Head, Tail, [NewVal | NewList])
> end.
>
this was the most useful answer for me --
i've missed at all that case statement could return any value ...
> However, there is no need for the first argument of initQuota. A
> usual formulation along your lines would have been
>
> initQuota(List) ->
> initQuota(List, []).
>
> initQuota([], Acc) ->
> lists:reverse(Acc);
> initQuota([{single, Val}|Tail], Acc) ->
> initQuota(Tail, [{single, Val, 0}|Acc]);
> initQuota([{range, Val1, Val2}|Tail], Acc) ->
> initQuota(Tail, [{range, Val1, Val2, 0}|Acc]).
>
> (Your formulation is equivalent to the above, but with
> initQuota(List=[_|_]) ->
> initQuota(List, []).)
>
> HTH,
>
> Carsten
>
in case of joining single element to list
[ Element | List ] is equal to [ Element ] ++ List
but [ List | Element ] creates nested list instead of
List ++ [ Element ]
why it works in this way -- so, are there any general rule which i can
learn, or it's a special case?
--
Gaspar Chilingarov
System Administrator
t +3749 419763
w www.web.am
e nm@REDACTED
More information about the erlang-questions
mailing list