I am trying to understand the usage of | in Erlang ,more specifically why is this expression not equivalent:
[4,5,6|7]=:=[4,5,6,7]
Isn't the | symbol used just for pattern matching , just to break the list in order to match it ?
The pipe | in order to create a proper list needs a list on the right side. To this right side the pipe appends elements from the left side. So to create [4, 5, 6, 7] with the pipe you need
[4, 5, 6 | [7]]
The version you tried creates so called improper list. You can read more about it at Understanding Lists.
Isn't the | symbol used just for pattern matching.
No, the cons (constructor) operator, |, can be used to both deconstruct a list with pattern matching and construct a list. Often, the last line of a function will be:
my_func(tail, [Head|Acc])
In that line, the cons operator creates a list for the second argument. The second argument is a list which adds the contents of the variable Head to the front of the Acc list.
Here is an example using the cons operator to both deconstruct a list and construct a list:
-module(a).
-compile(export_all).
get_evens(List) ->
get_evens(List, []). %% Add an empty list to the function call to accumulate the results.
get_evens([Head|Tail], Acc) when Head rem 2 == 0 -> %% deconstruct the first argument into Head and Tail
get_evens(Tail, [Head|Acc]); %% construct the second argument for the get_evens() function call
get_evens([_Head|Tail], Acc) ->
get_evens(Tail, Acc);
get_evens([], Acc) ->
lists:reverse(Acc).
In the shell:
2> c(a).
{ok,a}
3> a:get_evens([1, 2, 3, 4, 5]).
[2,4]
4>
The whole reason we can write recursive functions that will end when the empty list is found is because a list can be defined like this:
4> [1|[2|[3|[4|[5|[]]]]]].
[1,2,3,4,5]
Note how 5 is cons'ed with the empty list: 5|[]? That means when you get to the end of a list,[LastElmt | Tail] will match LastElmt to 5 and Tail to [], which means we can match a different function clause when we call get_evens(Tail, Acc), e.g.:
get_evens([], Acc) ->
lists:reverse(Acc).
Not related to the use of the |, but related to your question about pattern matching. The = is used for assignment, but because data is immutable in erlang, it is also a basic pattern match and test for equivalency.
Match Operator = in Patterns
Related
I am trying to figure out is there anyway that i can use append to make the three lists of integer inside a list to become a list of a list of integers, for example
[[1];[2];[3]] -> [[1;2;3]]
[] -> [[]]
[[]] -> []
but i am not sure how loop really in OCaml.
and the below is what i have tried, but i dont think it work
let rec ls (l : 'a list list) =
match l with
| [] -> []
| x :: y -> l#y
i have tried to use # to do function, but i don't how to remove the bracket.
Note that in your attempt, you never use x which is the head of the list, and the function is not recursive. It never calls itself. Note that # is never necessary in this exercise, which is good because it leads to some ugly performance implications.
Consider that you can use pattern-matching to identify whether a list is empty or not, and to extract elements from the head and the tail of a list. What should the result of flattening an empty list be? An empty list.
let rec flatten =
function
| [] -> []
Now, if the first list in the list of lists is empty, it should be the result of flattening the tail. This seems pretty obvious so far.
let rec flatten =
function
| [] -> []
| []::tl -> flatten tl
Now, if it's not empty then we can cons the first element of the first list onto the result of flattening... I'll leave that as an exercise for you to fill in.
let rec flatten =
function
| [] -> []
| []::tl -> flatten tl
| (x::xs)::tl -> x :: flatten ...
Looping via recursion
While OCaml does have imperative loops, it is much more idiomatic, especially when dealing with lists, to loop via recursion.
In order to use recursion to loop, there must be at least one exit case where the function does not recursively call itself, but there must also be at least one case where it does, and that function call must in some way update the state being passed in so that it converges on the exit case.
If the exit case is passing in an empty list, the recursive calls must get closer to passing in an empty list on each call or the recursion will never end.
If you did want to append...
If you decided you do like #, and don't care about O(n^2) runtime complexity, you can use it with List.fold_left to readily accomplish this goal.
# List.fold_left (#) [] [[1;2]; [3;4]];;
- : int list = [1; 2; 3; 4]
This is equivalent to [] # [1;2] # [3;4].
A method that returns a new list formed by applying the second argument as a modulus operand on each list member, with two arguments: a list and a numerical value.
My current method only applies modulus operand to the first element and not all the elements.
I'm trying to use the cons operator to build the new list.
modList([Head | Tail], Num) -> [Head rem Num | Tail].
You're on the right track.
You're writing a recursive function, so what you need next are two things:
The recursive step: At some point in the body of your function, you need to apply your same function to the rest of the list (i.e. modList(Tail)).
The base case: If you apply the recursive step repeatedly, since you're removing one element from the list on each iteration, at some point, you'll have a list that doesn't match your function head pattern ([Head | Tail]). That will lead to a function_clause error that you can fix by… of course… adding a clause for that list. Since that clause will likely not need to be recursive (i.e. it will return a hardcoded value), that will close the recursion loop and your recursive function will be complete.
Extra tip: It's generally more idiomatic to use snake_case instead of camelCase for function names, module names, and atoms in general in Erlang. In other words, a more common name for your function would be mod_list/2.
You can do something like
> Num = 5.
5
> [X rem Y || X <- [1, 2, 3, 4, 5, 6, 7], Y <- [Num]].
[1,2,3,4,0,1,2]
I have difficulty to understand the following Haskell symbol ([]:_).
I come cross a Haskell function called transpose
transpose::[[Int]]->[[Int]]
transpose ([]:_) = []
transpose x = (map head x):transpose(map tail x)
And I walk through a simple example.
transpose [[1,2],[3,4]]
=>[1,3]:transpose[2,4]
=>[1,3]:[2,4]:transpose[[],[]]
=>[1,3]:[2,4]:[]
=>[[1,3],[2,4]]
It seems to be make sense.
But If I pass [[], [1]] to the function, the output is still []
transpose [[], [1]]
=>[]
Can anyone explain why transpose return [] if I pass [[], [1]]?
This is not a symbol ([]:_) is simply a short version of:
( [] : _ )
^ ^ ^
| | wildcard
| empty list
list construct
The list construction is something like ( h :t ) with h the head (an element) and t the tail (either the remainder of the list, or the empty list). See CONS for more information.
So it means: match a list with as head the empty list and as tail a don't care.
This makes sense, since a transpose is only well defined on rectangular structures. What do you expect the transpose of [[],[1]] should be.
The reason that this line is necessary, is because in the second (recursive) call, you use the tails of all lists.
If you thus calculate the transpose of [[1,2,3],[4,5,6],[7,8,9]], you will first take the recursive case: as head, you emit all the heads of all the lists, so [1,4,7], and the recursion is done with the tails of all the lists, so you call it with transpose [[2,3],[5,6],[8,9]].
In the second round (recursive call), you emit again the heads of the lists, so [2,5,8] and do the recursive call on the tails: [[3],[6],[9]]. Next you emit again the heads [3,6,9], and now the recursive call on the tails is transpose [[],[],[]]. So a list of all empty lists. If the matrix condition hold however, it means we have finished. The pattern ( [] : _) matches [[],[],[]] so it will emit the empty list [].
It's not a matrix! Your first row is empty, therefore the first condition is satisfied and returns empty list as defined.
I want to make a new list that only contains the elements of the "list of lists" which have a length of 1.
The code that i provide gives a exception error: no function clause matching.
lists:foreach(fun(X) if length(X) =:= 1 -> [X] end, ListOfLists).
I am new to erlang, and I am having trouble finding an alternative way for writing this piece of code.
Can someone give me some advice on how to do so?
You can match in a list comprehension to get this quite naturally:
[L || L = [_] <- ListOfLists]
For example:
1> LoL = [[a], [b,c], d, [e], [f,g]].
[[a],[b,c],d,[e],[f,g]]
2> [L || L = [_] <- LoL].
[[a],[e]]
If you want the elements themselves (as in result [a, e] instead of [[a], [e]]) you can match on the element within the shape:
3> [L || [L] <- LoL].
[a,e]
Depending on the size of the lists contained within LoL, matching will be significantly faster than calling length/1 on every member. Calling length/1 and then testing the result requires traversing the entire list, returning a value, and then testing it. This is arbitrarily more overhead than checking if the second element of the list is a termination (in other words, if the "shape" of the data matches).
Regarding your attempt above...
As a newcomer to Erlang it might be helpful to become familiar with the basic functional list operations. They pop up over and over in functional (and logic) programming, and generally have the same names. "maps", "folds", "filters", "cons", "car" ("head" or "hd" or [X|_]), "cdr" ("tail" or "tl" or [_|X]), and so on.
Your original attempt:
lists:foreach(fun(X) if length(X) =:= 1 -> [X] end, ListOfLists).
This can't work because foreach/2 only returns ok, never any value. It is used only when you want to iterate over a list to get side-effects, not because you want to get a return value. For example, if I have a chat system the chat rooms have a list of current members, and broadcasting a message is really sending each chat message to each member in the list, I might do:
-spec broadcast(list(), unicode:chardata()) -> ok.
broadcast(Users, Message) ->
Forward = fun(User) -> send(User, Message) end,
lists:foreach(Forward, Users).
I don't care about the return value, really, and we aren't changing anything in the list Users or the Message. (Note that here we are using the anonymous function to capture the relevant state that it requires -- essentially currying out the Message value so we can present a function of arity 1 to the list operation foreach/2. This is where lambdas become most useful in Erlang vs named functions.)
When you want to take a list as an input and return a single, aggregate value (use some operation to roll all the values in the list into one) you can use a fold (you almost always want to use foldl/3, specifically):
4> lists:foldl(fun(X, A) when length(X) =:= 1 -> [X|A]; (_, A) -> A end, [], LoL).
[[e],[a]]
Broken down that reads as:
Single =
fun
(X, A) when length(X) =:= 1 -> [X|A];
(_, A) -> [X|A]
end,
ListOfSingles = lists:foldl(Single, [], LoL).
This is an anonymous function that has two clauses.
Written another way with a case we could do:
Single =
fun(X, A) ->
case length(X) of
1 -> [X|A];
_ -> A
end
end,
This is a matter of preference, as is the choice to inline that as an anonymous function within the call to foldl/3.
What you are really trying to do, though, is filter the list, and there is a universal list function called just that. You supply a testing function that returns a boolean -- if the test is true then the element will turn up in the output, otherwise it will not:
5> lists:filter(fun([X]) -> true; (_) -> false end, LoL).
[[a],[e]]
Breaking the lambda out as before:
6> Single =
6> fun([X]) -> true;
6> (_) -> false
6> end.
#Fun<erl_eval.6.54118792>
7> lists:filter(Single, LoL).
[[a],[e]]
Here we matched on the shape of the element in the anonymous function head. This filter is almost exactly equivalent to the list comprehension above (the only difference, really, is in the underlying implementation of list comprehensions -- semantically they are identical).
head' :: [a] -> a
head' [] = error "No head for empty lists!"
head' (x:_) = x
head' :: [a] -> a
head' xs = case xs of [] -> error "No head for empty lists!"
(x:_) -> x
I am asking for a fairly easy question which I don't understand.
In the code above, I see that it takes a list for an input.
But on the third line, it says (x:_) which confuses me.
Can anyone explain to me why they wrote (x:_) instead of [x:_]?
And plus, I don't understand what (x:_) means.
Thank you.
: is a constructor for lists, which takes the head of the new list as its left argument and the tail as its right argument. If you use it as a pattern like here that means that the head of the list you match is given to the left pattern and the tail to the right.
So in this case the head of the list is stored in the variable x and the tail is not used (_ means that you don't care about the value).
And yes, you can also use [] to pattern match against lists, but only lists of fixed size. For example the pattern [x] matches a list with exactly one element, which is then stored in the variable x. Likewise [x,y] would match a list with two elements.
Your proposed pattern [x:y] would thus match a list with one element, which matches the pattern x:y. In other words, it would match a list of lists which contains exactly one list.
This is a concept called pattern matching. : is an infix constructor, just like + is an infix function. In Haskell you pattern match with constructors.
(1 : 2 : 3 : [])
Is the same as [1, 2, 3], the square bracket notation is just syntactic sugar for creating lists.
Your pattern (x : _) means that you want to bind the first element of the list to x and that you do not care about the rest of the list _.