简体   繁体   中英

erlang list understanding problems

I am trying to work out an equation which is f(Ys) -> [Y * 2 || Y <- Ys, Y < 4]. f(Ys) -> [Y * 2 || Y <- Ys, Y < 4]. .

When I input a list f([5,1,2,6]). I get the result as [2,4] whilst I thought it should be [10, false] , which is derived from f([5,1,2,6]) -> [5 * 2 || 5 <- [1,2,6], 5 < 4] f([5,1,2,6]) -> [5 * 2 || 5 <- [1,2,6], 5 < 4] .

Can anyone tell me where I got it wrong or possibly walk through the correct process about how the correct result is achieved?

Of your input list elements, [5,6] are discarded because Y < 4 is false, leaving [1,2] .

Your output is evaluated as Y * 2 so a result of [2,4] works for me.

The list comprehension takes each value of Ys and discards those which where the predicates aren't true (ie where Y < 4 is not true) and then forms a list of the remaining input list where Y becomes those values. The result is transformed by Y * 2 though, so at that point [1,2] becomes [2,4] .

The list comprehension [Y * 2 || Y <- Ys, Y < 4] [Y * 2 || Y <- Ys, Y < 4] is directly equivalent to a filter over a list and then a multiplication. Consider that you couldn't multiply false * 2 even if that is what the guard in the list comprehension meant.

The filter test would look like fun(Y) -> Y < 4 end , which only returns a boolean :

-spec my_test(integer()) -> boolean().
my_test(Y) -> Y < 4.

To combine this into a function that returns a boolean or an integer you need something different:

-spec multiply_or_false(integer()) -> integer() | false.
multiply_or_false(Y) ->
    case Y < 4 of
         true  -> Y * 2;
         false -> false
    end.

This is a comparison and then a branch based on the outcome which returns either false or an integer.

If you did want to return a doubling or a boolean, you could use something like multiply_or_false/1 above in a map or list comprehension (they are exactly equivalent in this case):

[multiply_or_false(Y) || Y <- Ys].

or

lists:map(fun multiply_or_false/1, Ys).

Sometimes it is useful to force yourself to break elements of your code down into tiny little functions and spec them just to clarify what is really going on in your mind (whether or not the code remains in that form in the end).

The return value of the guard at the end of your list comprehension , which is Y < 4 , won't be included in your final list, instead if it evaluates to false the current element in the list will be excluded in the final list, and if it evaluates to true , the element will be included.

In your example because 5 is not less than 4 , so it doesn't include in the final list which is [2,4] .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM