I am trying to see if a letter exists in a list, i am currently doing like the following
sortedlist(Text)-> freq(lists:sort(Text)).
freq(List) -> freq (List, [], []).
freq(List, Freq, CheckedLetters) when length(List) > 0 ->
[CurrHead|T]= List,
Checked = lists:member(CurrHead,CheckedLetters),
case Checked of
false -> CheckedLetters++[CurrHead],
freq(T,Freq++[{CurrHead,count(CurrHead, List)}],CheckedLetters);
true -> freq(T,Freq,CheckedLetters)
end;
freq([],Freq,CheckedLetters)-> Freq.
List contains user entered letters
CheckedLetters is an empty list, that will keep track of the already examined letters
But I am receiving the following erlang exception at the case-statement line (the lines with **).
error: no match of right hand side value []
What is the problem here? I am been blindy staring at those lines.
The end condition is missing in your recursive function. So when list become empty (each time you recall the function with the tail it is getting smaller), the match [CurrHead|T]= List, fails with error.
You have to add a clause to manage the end of recursion:
freq([], Freq, CheckedLetters) when length(List) > 0 ->
{Freq, CheckedLetters};
freq(List, Freq, CheckedLetters) when length(List) > 0 ->
[CurrHead|T]= List,
Checked = lists:member(CurrHead,CheckedLetters),
case Checked of
true -> CheckedLetters++[CurrHead],
freq(T,Freq++[{CurrHead,count(CurrHead, List)}],CheckedLetters);
false -> freq(T,Freq,CheckedLetters)
end;
I think you will have also to review the inside operation, I doubt it is doing what you expect. in particular the line CheckedLetters++[CurrHead], has no effect.
[edit]
Don't forget that variables are not mutable in erlang. So the line CheckedLetters++[CurrHead] simply evaluates a new list and forget the result (in fact I am not sure it does anything since you do not bound this evaluation to any variable, and the compiler knows it).
I guess that what you want to do is:
case Checked of
true ->
freq(T,Freq++[{CurrHead,count(CurrHead, List)}],CheckedLetters++[CurrHead]);
false ->
freq(T,Freq,CheckedLetters)
end;
Next you should have a look at Freq++[{CurrHead,count(CurrHead, List)}], I think it isn't correct.
The only piece of code in that block that could error: no match of right hand side value [] is [CurrHead|T]= List, as Steve Vinoski said. Likely there is some scenario where List is an empty list instead of a list of letters.
Also, the last line in the code block you shared:
case Checked == false of
...
end
Can be simplified to:
case Checked of
true ->
...
false ->
...
end
Since Checked is the return value of lists:member/2, and lists:member/2 is guaranteed to return a boolean, you can safely match directly on the true and false atoms.
lists:member/2 documentation: http://erlang.org/doc/man/lists.html#member-2
Related
I was given a question which was:
given a number N in the first argument selects only numbers greater than N in the list, so that
greater(2,[2,13,1,4,13]) = [13,4,13]
This was the solution provided:
member(_,[]) -> false;
member(H,[H|_]) -> true;
member(N,[_,T]) -> member(N,T).
I don't understand what "_" means. I understand it has something to do with pattern matching but I don't understand it completely. Could someone please explain this to me
This was the solution provided:
I think you are confused: the name of the solution function isn't even the same as the name of the function in the question. The member/2 function returns true when the first argument is an element of the list provided as the second argument, and it returns false otherwise.
I don't understand what "_" means. I understand it has something to do with pattern matching but I don't understand it completely. Could someone please explain this to me
_ is a variable name, and like any variable it will match anything. Here are some examples of pattern matching:
35> f(). %"Forget" or erase all variable bindings
ok
45> {X, Y} = {10, 20}.
{10,20}
46> X.
10
47> Y.
20
48> {X, Y} = {30, 20}.
** exception error: no match of right hand side value {30,
20}
Now why didn't line 48 match? X was already bound to 10 and Y to 20, so erlang replaces those variables with their values, which gives you:
48> {10, 20} = {30, 20}.
...and those tuples don't match.
Now lets try it with a variable named _:
49> f().
ok
50> {_, Y} = {10, 20}.
{10,20}
51> Y.
20
52> {_, Y} = {30, 20}.
{30,20}
53>
As you can see, the variable _ sort of works like the variable X, but notice that there is no error on line 52, like there was on line 48. That's because the _ variable works a little differently than X:
53> _.
* 1: variable '_' is unbound
In other words, _ is a variable name, so it will initially match anything, but unlike X, the variable _ is never bound/assigned a value, so you can use it over and over again without error to match anything.
The _ variable is also known as a don't care variable because you don't care what that variable matches because it's not important to your code, and you don't need to use its value.
Let's apply those lessons to your solution. This line:
member(N,[_,T]) -> member(N,T).
recursively calls the member function, namely member(N, T). And, the following function clause:
member(_,[]) -> false;
will match the function call member(N, T) whenever T is an empty list--no matter what the value of N is. In other words, once the given number N has not matched any element in the list, i.e. when the list is empty so there are no more elements to check, then the function clause:
member(_,[]) -> false;
will match and return false.
You could rewrite that function clause like this:
member(N, []) -> false;
but erlang will warn you that N is an unused variable in the body of the function, which is a way of saying: "Are you sure you didn't make a mistake in your function definition? You defined a variable named N, but then you didn't use it in the body of the function!" The way you tell erlang that the function definition is indeed correct is to change the variable name N to _ (or _N).
It means a variable you don't care to name. If you are never going to use a variable inside the function you can just use underscore.
% if the list is empty, it has no members
member(_, []) -> false.
% if the element I am searching for is the head of the list, it is a member
member(H,[H|_]) -> true.
% if the elem I am searching for is not the head of the list, and the list
% is not empty, lets recursively go look at the tail of the list to see if
% it is present there
member(H,[_|T]) -> member(H,T).
the above is pseudo code for what is happening. You can also have multiple '_' unnamed variables.
According to Documentation:
The anonymous variable is denoted by underscore (_) and can be used when a variable is required but its value can be ignored.
Example:
[H, _] = [1,2] % H will be 1
Also documentation says that:
Variables starting with underscore (_), for example, _Height, are normal variables, not anonymous. They are however ignored by the compiler in the sense that they do not generate any warnings for unused variables.
Sorry if this is repetitive...
What does (_,[]) mean?
That means (1) two parameters, (2) the first one matches anything and everything, yet I don't care about it (you're telling Erlang to just forget about its value via the underscore) and (3) the second parameter is an empty list.
Given that Erlang binds or matches values with variables (depending on the particular case), here you're basically looking to a match (like a conditional statement) of the second parameter with an empty list. If that match happens, the statement returns false. Otherwise, it tries to match the two parameters of the function call with one of the other two statements below it.
I'm trying to implement the a split method in Erlang that is supposed to split a string like "i am on the mountain top" into a list like ["i","am","on","the","mountain","top"].
Here is my code (exercise.erl):
-module(exercise).
-import(oi,[read/1]).
-export([split/4]).
split(Text,_,Result,_) when Text == [] -> Result;
split([Head|Tail],Separator,Result,WordSummer) when Head == Separator ->
split(Tail,Separator,[Result|lists:flatten(WordSummer)],[]);
split([Head|Tail],Separator,Result,WordSummer) ->
split(Tail,Separator,Result,[WordSummer|Head]).
The problem I'm having is that when calling my exported function I get the following error:
9> c(exercise).
{ok,exercise}
10> exercise:split("sdffdgfdg dgdfgfg dgdfg dgdfgd dfgdfgdfgtrty hghfgh",$ ,[],[]).
** exception error: no function clause matching lists:do_flatten(103,[]) (lists.erl, line 627)
in function lists:do_flatten/2 (lists.erl, line 628)
in call from exercise:split/4 (exercise.erl, line 9)
11>
How can I solve this?
Two things:
The [WordSummer|Head] in the last line is creating an improper list because Head is an integer (one character of the input string). This is causing the error you're seeing. You probably meant [WordSummer, Head].
[Result|lists:flatten(WordSummer)] is creating a nested list instead of a list of strings. To append one item to a list, use ++ and wrap the right side in a list: Result ++ [lists:flatten(WordSummer)]
Final code:
split(Text,_,Result,_) when Text == [] -> Result;
split([Head|Tail],Separator,Result,WordSummer) when Head == Separator ->
split(Tail,Separator,Result ++ [lists:flatten(WordSummer)],[]);
split([Head|Tail],Separator,Result,WordSummer) ->
split(Tail,Separator,Result,[WordSummer, Head]).
Test:
1> c(exercise).
{ok,exercise}
2> exercise:split("sdffdgfdg dgdfgfg dgdfg dgdfgd dfgdfgdfgtrty hghfgh",$ ,[],[]).
["sdffdgfdg","dgdfgfg","dgdfg","dgdfgd","dfgdfgdfgtrty"]
There's still a bug where the last segment is being ignored. I'll let you figure that out (hint: you need to consider WordSummer in the first clause of the function).
i tried to implement binary_search in erlang :
binary_search(X , List) ->
case {is_number(x) , is_list(List)} of
{false , false} -> {error};
{false , true} -> {error} ;
{true , false} -> {error} ;
{true , true} ->
Length = length(List) ,
case Length of
0 -> {false};
1 -> case lists:member(X , List) of
true -> {true};
false -> {false}
end ;
_ ->
Middle = (Length + 1) div 2 ,
case X >= Middle of
true -> binary_search(X , lists:sublist(List , Middle , Length));
false -> binary_search(X , lists:sublist(List , 1 , Middle))
end
end
end .
However when i try to compile it , i get the following error : "this clause cannot match because of different types/sizes" in the two lines :
{true , false} -> {error} ;
{true , true} ->
is_number(x) will always return false since you made a typo: x instead of X, an atom instead of a variable.
BTW, I don't know what you are experiencing, but the whole code can be written as:
binary_search(X , [_|_] = List) when is_number(X) ->
{lists:member(X,List)};
binary_search(_,_) -> {error}.
Context: The OP's post appears to be a learning example -- an attempt to understand binary search in Erlang -- and is treated as one below (hence the calls to io:format/2 each iteration of the inner function). In production lists:member/2 should be used as noted by Steve Vinoski in a comment below, or lists:member/2 guarded by a function head as in Pascal's answer. What follows is a manual implementation of binary search.
Pascal is correct about the typo, but this code has more fundamental problems. Instead of just finding the typo let's see if we can obviate the need for this nested case checking entirely.
(The code as written above won't work anyway because X should not represent the value of an index, but rather the value that is held at that index, so Middle will likely never match X. Also, there is another issue: you don't cover all the base cases (cases in which you should stop recursing). So the inner function below covers them all up front as matches within the function head, so it is more obvious how the search works. Note the Middle + 1 when X > Value, by the way; contemplate why this is necessary.)
Two main notes on Erlang style
First: If you receive the wrong sort of data, just crash, don't return an error. With that in mind, consider using a guard.
Second: If you find yourself doing lots of cases, you can usually simplify your life by making them named functions. This gives you two advantages:
A much better crash report than you will get within nested case expressions.
A named, pure function can be tested and even formally verified rather easily if it is small enough -- which is also pretty cool. (As a side note, the religion of testing tests my patience and sanity at times, but when you have pure functions you actually can test at least those parts of your program -- so distilling out as much of this sort of thing as possible is a big win.)
Below I do both, and this should obviate the issue you ran into as well as make things a bit easier to read/sort through mentally:
%% Don't return errors, just crash.
%% Only check the data on entry.
%% Guarantee the data is sorted, as this is fundamental to binary search.
binary_search(X, List)
when is_number(X),
is_list(List) ->
bs(X, lists:sort(List)).
%% Get all of our obvious base cases out of the way as matches.
%% Note the lack of type checking; its already been done.
bs(_, []) -> false;
bs(X, [X]) -> true;
bs(X, [_]) -> false;
bs(X, List) ->
ok = io:format("bs(~p, ~p)~n", [X, List]),
Length = length(List),
Middle = (Length + 1) div 2,
Value = lists:nth(Middle, List),
% This is one of those rare times I find an 'if' to be more
% clear in meaning than a 'case'.
if
X == Value -> true;
X > Value -> bs(X, lists:sublist(List, Middle + 1, Length));
X < Value -> bs(X, lists:sublist(List, 1, Middle))
end.
How can get the type of a list. I want to execute the code if the list is proplist.
Let us say L = [a,1,b,2,c,3, ...]. Is the list L, I'm converting it to proplist like
L = [{a,1}, {b,2}, {c,3}, ...].
How can I determine whether the list is a proplist? erlang:is_list/1 is not useful for me.
You can use something like:
is_proplist([]) -> true;
is_proplist([{K,_}|L]) when is_atom(K) -> is_proplist(L);
is_proplist(_) -> false.
but necessary to consider that this function cannot be used in guards.
You'd need to check whether every element of the list is a tuple of two elements. That can be done with lists:all/2:
is_proplist(List) ->
is_list(List) andalso
lists:all(fun({_, _}) -> true;
(_) -> false
end,
List).
This depends on which definition of "proplist" you use, of course. The above is what is usually meant by "proplist", but the documentation for the proplists module says:
Property lists are ordinary lists containing entries in the form of either tuples, whose first elements are keys used for lookup and insertion, or atoms, which work as shorthand for tuples {Atom, true}.
So I've been using Erlang for the last eight hours, and I've spent two of those banging my head against the keyboard trying to figure out the exception error my console keeps returning.
I'm writing a dice program to learn erlang. I want it to be able to call from the console through the erlang interpreter. The program accepts a number of dice, and is supposed to generate a list of values. Each value is supposed to be between one and six.
I won't bore you with the dozens of individual micro-changes I made to try and fix the problem (random engineering) but I'll post my code and the error.
The Source:
-module(dice2).
-export([d6/1]).
d6(1) ->
random:uniform(6);
d6(Numdice) ->
Result = [],
d6(Numdice, [Result]).
d6(0, [Finalresult]) ->
{ok, [Finalresult]};
d6(Numdice, [Result]) ->
d6(Numdice - 1, [random:uniform(6) | Result]).
When I run the program from my console like so...
dice2:d6(1).
...I get a random number between one and six like expected.
However when I run the same function with any number higher than one as an argument I get the following exception...
**exception error: no function clause matching dice2:d6(1, [4|3])
... I know I I don't have a function with matching arguments but I don't know how to write a function with variable arguments, and a variable number of arguments.
I tried modifying the function in question like so....
d6(Numdice, [Result]) ->
Newresult = [random:uniform(6) | Result],
d6(Numdice - 1, Newresult).
... but I got essentially the same error. Anyone know what is going on here?
This is basically a type error. When Result is a list, [Result] is a list with one element. E.g., if your function worked, it would always return a list with one element: Finalresult.
This is what happens (using ==> for "reduces to"):
d6(2) ==> %% Result == []
d6(2, [[]]) ==> %% Result == [], let's say random:uniform(6) gives us 3
d6(1, [3]) ==> %% Result == 3, let's say random:uniform(6) gives us 4
d6(0, [4|3]) ==> %% fails, since [Result] can only match one-element lists
Presumably, you don't want [[]] in the first call, and you don't want Result to be 3 in the third call. So this should fix it:
d6(Numdice) -> Result = [], d6(Numdice, Result). %% or just d6(Numdice, []).
d6(0, Finalresult) -> {ok, Finalresult};
d6(Numdice, Result) -> d6(Numdice - 1, [random:uniform(6) | Result]).
Lesson: if a language is dynamically typed, this doesn't mean you can avoid getting the types correct. On the contrary, it means that the compiler won't help you in doing this as much as it could.