[erlang-questions] queue:split/2 unsafe!
Ivan Uemlianin
ivan@REDACTED
Wed Apr 10 14:51:34 CEST 2013
Dear All
Thanks for your comments.
(Y) is exactly my use case. You are right 'split_at_most' is a better name.
Best wishes
Ivan
On 10/04/2013 01:21, Richard A. O'Keefe wrote:
> There are actually two different things that someone might want to do:
>
> (X) I want *exactly* N items from this sequence:
> n -> seq -> (pref, suff) where pref++suff == seq && #pref == n
>
> (Y) I want *at most* N items from this sequence:
> n -> seq -> (pref, suff) where pref++suff == seq &&
> #pref = min(#seq, n)
>
> If you want exactly N items and there are not N items available,
> that's an error.
> If you want at most N items and there are not N items available,
> that is *not* an error, it's something you had in mind when you asked.
>
> I agree with Fred Herbert that existing functions designed for use
> case (X) should not be changed; that guarantee that you got as much
> as you asked for is too precious to lose.
>
> I also agree with Ivan Uemlianin that use case (Y) is also important
> enough to support (think of Unix read(2)).
>
> I disagree with him that 'safe_split' is a good name for use case (Y).
> There are plenty of situations where (X) is the safe alternative.
>
> So why not add
>
> .. in lists.erl ..
>
> %% split_at_most(N, L) returns {P, S}
> %% such that L = P++S and length(P) == min(N, length(L)).
> %% If you need length(P) == N exactly, you must use split/2.
> %% This is for use when you are happy with a short result.
>
> -spec(split_at_most/2 :: (non_neg_integer(),[T]) -> {[T],[T]}).
>
> split_at_most(N, L) when is_integer(N), N >= 0, is_list(L) ->
> split_at_most(N, L, []).
>
> split_at_most(N, [H|T], PR) when N > 0 ->
> split_at_most(N-1, T, [H|PR]);
> split_at_most(_, S, PR) ->
> {reverse(PR), S}.
>
> Does anyone else find it confusing that it's "listS.erl" (plural)
> but "queue.erl" (singular)? Is there only one queue?
>
> %% split_at_most(N, Q) returns {P, S}
> %% such that P and S are queues and concatenating S after P
> %% gives you a queue with the same elements as Q in the same
> %% logical order, and length(P) == min(N, length(Q)).
> %% If you need length(P) == N exactly, you must use split/2.
> %% This is for use when you are happy with a short result.
>
> -spec(split_at_most/2 :: (non_neg_integer(),{[T],[T]}) ->
> {{[T],[T]},{[T],[T]}}).
>
> split_at_most(N, {Back,Front})
> when is_integer(N), N >= 0, is_list(Back), is_list(Front) ->
> LF = length(Front),
> if LF >= N ->
> {PF, SF} = lists:split_at_most(N, Front),
> {f2r(PF), {Back,SF}}
> ; true ->
> {PB, SB} = lists:split_at_most(N-LF, lists:reverse(Back)),
> {f2r(Front++PB), f2r(SB)}
> end.
>
> This code has been tested.
>
> However, looking through queue.erl has convinced me, the next
> time I need queues, to write my own module.
>
--
============================================================
Ivan A. Uemlianin PhD
Llaisdy
Speech Technology Research and Development
ivan@REDACTED
www.llaisdy.com
llaisdy.wordpress.com
github.com/llaisdy
www.linkedin.com/in/ivanuemlianin
festina lente
============================================================
More information about the erlang-questions
mailing list