Weird lists:dropwhile/2 behavior?

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Weird lists:dropwhile/2 behavior?

fxmy wang-2

Hello guys,

Just encountered this:
Erlang/OTP 18 [erts-7.0.3] [source-5991161] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V7.0.3  (abort with ^G)
1> F = fun(_) -> true end.
#Fun<erl_eval.6.54118792>
2> K = fun(Elem) -> Elem > 3 end.
#Fun<erl_eval.6.54118792>
3> lists:dropwhile(F, [1,2,3,4,5]).
[]
4> lists:dropwhile(K, [1,2,3,4,5]).
[1,2,3,4,5]

Is this behavior expected?
Am I missing something?

​​


​Cheers,

Fxmy.​


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Weird lists:dropwhile/2 behavior?

Sergej Jurečko
You probably should be using lists:filter for K, or better yet a list comprehension. 
lists:dropwhile will stop processing as soon as K returns false.

Sergej

On 21 Feb 2016, at 13:39, fxmy wang <[hidden email]> wrote:

Hello guys,

Just encountered this:
Erlang/OTP 18 [erts-7.0.3] [source-5991161] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V7.0.3  (abort with ^G)
1> F = fun(_) -> true end.
#Fun<erl_eval.6.54118792>
2> K = fun(Elem) -> Elem > 3 end.
#Fun<erl_eval.6.54118792>
3> lists:dropwhile(F, [1,2,3,4,5]).
[]
4> lists:dropwhile(K, [1,2,3,4,5]).
[1,2,3,4,5]

Is this behavior expected?
Am I missing something?

​​



​Cheers,


Fxmy.​


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Weird lists:dropwhile/2 behavior?

dmkolesnikov
In reply to this post by fxmy wang-2
Hello,

This is correct behavior.

http://erldocs.com/17.5/stdlib/lists.html?i=1&search=lists:drop#dropwhile/2
"Drops elements Elem from List1 while Pred(Elem) returns true and returns the remaining list."

Your first case: the predicate return true, empty list is the correct result.
Your second case: the predicate return false for the first element, remaining list is returned.

- Dmitry  


> On Feb 21, 2016, at 2:39 PM, fxmy wang <[hidden email]> wrote:
>
> Hello guys,
>
> Just encountered this:
> Erlang/OTP 18 [erts-7.0.3] [source-5991161] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]
>
> Eshell V7.0.3  (abort with ^G
> )
>
> 1> F = fun(_) -> true end
> .
>
> #Fun<erl_eval.6.54118792
> >
>
> 2> K = fun(Elem) -> Elem > 3 end
> .
>
> #Fun<erl_eval.6.54118792
> >
>
> 3> lists:dropwhile(F, [1,2,3,4,5
> ]).
> []
>
> 4> lists:dropwhile(K, [1,2,3,4,5
> ]).
> [
> 1,2,3,4,5
> ]
>
> Is this behavior expected?
> Am I missing something?
>
> ​​
>
>
>
>
> ​Cheers,
>
>
> Fxmy.​
>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Weird lists:dropwhile/2 behavior?

Jesper Louis Andersen-2
In reply to this post by fxmy wang-2

On Sun, Feb 21, 2016 at 1:39 PM, fxmy wang <[hidden email]> wrote:
Is this behavior expected?

yes. To make it explicit:

In lists:dropwhile(fun(E) -> E > 3 end, [1,2,3,4,5]), we first check if 1 > 3. This is false, so we stop dropping and return the remainder of the list, which is [1,2,3,4,5].


--
J.

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Weird lists:dropwhile/2 behavior?

fxmy wang-2
Thanks guys, somehow the doc gives me a feeling that lists:dropwhile will scan through all the list no matter Pred(Elem) returns 'true' or 'false'. =)

Cheers

2016-02-21 21:36 GMT+08:00 Jesper Louis Andersen <[hidden email]>:

On Sun, Feb 21, 2016 at 1:39 PM, fxmy wang <[hidden email]> wrote:
Is this behavior expected?

yes. To make it explicit:

In lists:dropwhile(fun(E) -> E > 3 end, [1,2,3,4,5]), we first check if 1 > 3. This is false, so we stop dropping and return the remainder of the list, which is [1,2,3,4,5].


--
J.


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Weird lists:dropwhile/2 behavior?

zxq9-2
In reply to this post by Jesper Louis Andersen-2
On 2016年2月21日 日曜日 14:36:05 Jesper Louis Andersen wrote:

> On Sun, Feb 21, 2016 at 1:39 PM, fxmy wang <[hidden email]> wrote:
>
> > Is this behavior expected?
>
>
> yes. To make it explicit:
>
> In lists:dropwhile(fun(E) -> E > 3 end, [1,2,3,4,5]), we first check if 1 >
> 3. This is false, so we stop dropping and return the remainder of the list,
> which is [1,2,3,4,5].

Hi Fxmy.

To follow up with a counter example:

  1> J = fun(Z) -> Z < 3 end.
  #Fun<erl_eval.6.54118792>
  2> lists:dropwhile(J, [1,2,3,4,5]).
  [3,4,5]

Compare that with yours:

  2> K = fun(Elem) -> Elem > 3 end.
  #Fun<erl_eval.6.54118792>
  4> lists:dropwhile(K, [1,2,3,4,5]).
  [1,2,3,4,5]

And now an example over a valley:

  3> Q = fun(Z) -> Z > 3 end.
  #Fun<erl_eval.6.54118792>
  4> lists:dropwhile(Q, [5,4,3,2,1,2,3,4,5]).
  [3,2,1,2,3,4,5]

Just like it says on the box.

-Craig
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Weird lists:dropwhile/2 behavior?

Richard A. O'Keefe-2
In reply to this post by fxmy wang-2


On 22/02/16 1:39 am, fxmy wang wrote:
   K = fun (E) -> E > 3 end.
   lists:dropwhile(K, [1,2,3,4,5]).

What should we expect that to do?
dropwhile(Test, List) says "throw away the longest prefix
of List such that every element of the prefix satisfies the
Test."  What is the longest prefix of [1,2,3,4,5] such that
every element is greater than 3?  The empty list.  So we
expect the answer [1,2,3,4,5], and indeed, that's what we get.

   lists:filter(K, [3,1,4,2,5])
will of course answer [4,5], because filter is defined to look
at all the elements, not just a prefix.

Without looking at the source code, it will be something like

dropwhile(F, L = [X|Xs]) ->
     case F(X)
       of true  -> dropwhile(F, Xs)
        ; false -> L
     end;
dropwhile(_, L) ->
     L.

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Weird lists:dropwhile/2 behavior?

Richard A. O'Keefe-2
In reply to this post by fxmy wang-2


On 22/02/16 2:40 am, fxmy wang wrote:
> Thanks guys, somehow the doc gives me a feeling that lists:dropwhile
> will scan through all the list no matter Pred(Elem) returns 'true' or
> 'false'. =)

The documentation is unfortunately sparse.

dropwhile(Pred, List1) -> List2

Types:

Pred = fun((Elem :: T) -> boolean())
List1 = List2 = [T]
T = term()

Drops elements Elem from List1 while Pred(Elem) returns true and returns
the remaining list.

You have to read closely to see the word WHILE there.
For takewhile/2 it's clearer:

takewhile(Pred, List1) -> List2

Types:

Pred = fun((Elem :: T) -> boolean())
List1 = List2 = [T]
T = term()
Takes elements Elem from List1 while Pred(Elem) returns true, that is,
the function returns the longest prefix of the list for which all
elements satisfy the predicate.

For all L and for all F such that [F(X) || X <- L] contains only true
and false,
takewhile(F, L) ++ dropwhile(F, L) == L.

The takewhile and dropwhile functions (why on earth are they not
take_while and drop_while? since when has Erlang runwordstogetherlikeC?)
are not unique to Erlang.   For example, in Haskell
 > dropWhile (> 3) [1..5]
[1,2,3,4,5]

I propose the following revision to the documentation.

%% dropwhile

Let List == Prefix ++ Suffix where Pred(X) is true for every X in Prefix
and Prefix is as long as possible.  dropwhile(Pred, List) returns Prefix.
See takewhile/2.

%% takewhile

Let List == Prefix ++ Suffix where Pred(X) is true for every X in Prefix
and Prefix is as long as possible.  takewhile(Pred, List) returns Suffix.
See dropwhile/2.



_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions