2008/5/19 Steve Davis <<a href="mailto:steven.charles.davis@gmail.com">steven.charles.davis@gmail.com</a>>:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
To give a simple example below -- I wish to perform check2() only on the<br>
elements that pass check() and I can't see an elegant way to do it!<br>
<br>
-module(filter).<br>
-export([init/0]).<br>
<br>
init() -><br>
        L = [1,2,3,4,5,6,7,8,9,10],<br>
        check(L),<br>
        check2(L, []).</blockquote><div><br>The thing to remember here is that filter, and hence check/1, return the list of filtered elements. You use this in check2/2. So init/1 should be written:<br><br>init() -><br>
    L0 = [1,2,3,4,5,6,7,8,9,10],<br>    L1 = check(L0),<br>    check2(L1, []).<br><br>If you have a sequence of checks you would get:<br><br>    L1 = check1(L0),<br>    L2 = check2(L1),<br>    L3 = check3(L2),<br>    ...<br>
<br>This could be written as folding a list of checks over the returned lists:<br><br>   Checks =<br>        [fun (L) ->check1(L) end,<br>         fun (L) -> check2(L) end,<br>         ...],<br>    lists:foldl(fun (C, L) -> C(L) end, InitialList, Checks)<br>
<br>If this is clearer is a matter of taste. It is at least easier to modify checks list without having to change variable names. :-)<br><br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">

check(L) -> lists:filter(fun(X) -> X rem 2 =:= 0 end, L).<br>
<br>
check2([], A) -> A;<br>
check2([H | T], A) -><br>
        C = lists:filter(fun(X) -> (X + H) rem 3 =:= 0 end, T),<br>
        C1 = [{H, X, H / X} || X <- C],<br>
        check2(T, lists:append(A, C1)).</blockquote><div><br>You can combine the filter and the list comprehension into one list comprehension:<br><br>    C1 = [{H,X,H/X} || X <- T, (X+H) rem 3 =:= 0 ]<br><br>In your code you are really using the list comprehension as a map.<br>
<br>A final point: depending on the length of the output list and the significance of the order of elements it might be better to push the new elements onto the accumulator list and reverse the result at the end.<br><br>Although I realise that this is just example code. :-) Out of interest what are doing?<br>
<br>Robert<br><br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
In my actual code I have 5 non-trivial filters and I'm trying at all<br>
costs to avoid duplication of tests, The example code below exactly<br>
specifies the issue (without the detail). i.e. for members of the list<br>
data that pass the initial check (in this case they are even numbers),<br>
perfom check2... check2 requires that each candidate element should be<br>
checked against all other members of the list (but not itself) and<br>
should not duplicate any pairwise test in the "expensive" check2...<br>
(my data is actually records so avoiding the issue by using the fact<br>
that value of the list elements in the example is not going to help!)<br>
<br></blockquote></div><br>