Erlang receive after - parallel-processing

I am having issues making my receive after function work in Erlang, I've googled and banged my head against this for some time now but can't seem to figure it out and would need some help. I have a process which runs the following process and waits for messages.
% Waits for messages, and puts them into the list.
% If the list has the same length as the Length variable
% which is the original provided list, then it means we are done
% and can print the results.
% If the MaxTime has passed it should just print the provided list.
wait_max_time(List, Length, MaxTime) ->
io:format("I am ~p and waiting...~n", [self()]),
receive
X ->
Results = List ++ [X],
case length(Results) =:= Length of
true ->
io:format("~p~n", [Results]),
exit(self());
false ->
wait(Results, Length)
end
after MaxTime -> io:format("List is ~p~n", [List])
end.
Everything above the after seems to work fine, it always computes and I've confirmed it with print statements.
But for calculations which takes too long time, I simply want to print the list it got and not continue. But after never gets runned in my code, what am I doing wrong?

As Dogbert pointed out in the comment, I completely missed that I forgot to change a name of a function under false which called another function which didn't have the timeout.
Problem is solved, thanks.

Related

Prolog looking for the inorder location of an element in tree(without using lists)

I am trying to go through a binary tree in an inorder traveling method
my target is to find the occurance of a specific key in the tree
for example,
i have the following tree:
t(t(t(nil,"d",t(nil,"g",nil)),"b",t(nil,"e",nil)),"a",t(t(nil,"f",t(nil,"h",nil)),"c",nil))
when i will use my inorder_finder i will get the following:
for "c" i will get 8
for "d" i will get 1
for "w" i will get -1
I have come up to the following code:
inorder_finder(nil,_,_,0).
inorder_place(t(_,X,_),X,Count,Place) :-
Place is Count+1.
inorder_place(t(L,_,R),Wanted,Count,Place) :-
inorder_place(L,Wanted,Count+1,Place),
Place<1,
inorder_place(R,Wanted,Count+1,Place),
Place<1,
Count = Count+1.
and i call the following predicate:
inorder_finder inorder_place(t(t(t(nil,"d",t(nil,"g",nil)),"b",t(nil,"e",nil)),"a",t(t(nil,"f",t(nil,"h",nil)),"c",nil)),"c",1,Place)
but it doesnt work at the moment. (just always returns false)
any ideas?
update: I have updated the code according to the comments i got - it still returns false and doesnt work as i would like it to
Most obvious errors have been mentioned in comments, what still remain are:
Place<1 : I don't get why?? Place may has value greater than 1.
inorder_place: never defined...
inorder_place(t(_,X,_),X,Count,Place):-Place is Count+1.: even if you find the letter you need first recursively enumerate the left branch of tree and then Place of wanted letter (see answer below)
I think the problem could be solved in two parts, one in-order-enumerate all nodes then simply traverse until you find the right node. Though I didn't followed this version (even it is more clear) since with a simple-mixed solution it is more efficient since you may not need to enumerate all nodes. For this attempt that you're trying to do I think you need two counters - first one the counter when calling inorder_find(..) e.g when entering, second counter will return where the counting stopped in order to continue from there in the right branch of tree.
inorder_finder inorder_place(...):still not valid syntax for calling the predicate- it should return error not false...
My implementation:
inorder_finder(nil,_,Count,Count,-1).
inorder_finder(t(L,X,_),X,Count,Count2,Place):-
inorder_finder(L,X,Count,Count3,_),
Place is Count3+1,Count2 is Place.
inorder_finder(t(L,X,R),Wanted,Count,Count2,Place):-
dif(X,Wanted),
inorder_finder(L,Wanted,Count,Count3,Place1),
Count4 is Count3+1,
inorder_finder(R,Wanted,Count4,Count2,Place2),
Place is max(Place1,Place2).
Examples:
?- inorder_finder(t(t(t(nil,"d",t(nil,"g",nil)),"b",t(nil,"e",nil)),"a",t(t(nil,"f",t(nil,"h",nil)),"c",nil)),"c",0,_,P).
P = 8 ;
false.
?- inorder_finder(t(t(t(nil,"d",t(nil,"g",nil)),"b",t(nil,"e",nil)),"a",t(t(nil,"f",t(nil,"h",nil)),"c",nil)),"W",0,_,P).
P = -1.
?- inorder_finder(t(t(t(nil,"d",t(nil,"g",nil)),"b",t(nil,"e",nil)),"a",t(t(nil,"f",t(nil,"h",nil)),"c",nil)),"d",0,_,P).
P = 1 ;
false.

persian language processing prolog

This is my prolog code, which gave me the following error:
ERROR: Out of global stack
hasA(S,A):- name(S,L1),
compar(L1,A).
compar([H1,H2|T1],T1):- H1 == 1575, H2 == 1740.
neda(H,A):- hasA(H,Z1),
append(A,[1575,1740],A),
state(Z1,Z2),
append(A,Z2,A).
state([H|T],T):- H == 32.
state(A,A).
What is wrong? Can you help me with it?
Assuming that you call neda(H,A) with A being a free variable you end up calling append(A,[1575,1740],A) with A being a free variable as well. However, traditionally, append is implemented as
append([],Ys,Ys).
append([X|Xs],Ys,[X|Zs]) :- append(Xs,Ys,Zs).
Unification of append(A,[1575,1740],A) with append([],Ys,Ys) fails since it requires A to be [], on the one hand, and [1575,1740], on the other hand. Hence, Prolog tries to unify append(A,[1575,1740],A) with append([X|Xs],Ys,[X|Zs]) and succeeds with {A/[X|Xs], Ys/[1575,1740], Xs/Zs} which leads to the call append(Xs,[1575,1740],Xs) and the process repeats, i.e., Prolog enters an infinite recursion and ultimately runs out of stack.
If I guess your intention correctly, you first would like to append [1575,1740] to A and then to append Z2. This would mean that you need to introduce two new variables, say A1 and A2, to record the state of A after each appending step:
neda(H,A):- hasA(H,Z1),
append(A,[1575,1740],A1),
state(Z1,Z2),
append(A1,Z2,A2).
Beware, however, that with A being a free variable on backtracking this code will generate lists of increasing length; is this what you want?

How do i count words in prolog?

I try to count words in a string in prolog. Like "No, I am definitely not a pie!"
To give me the number 7 and next example "w0w such t3xt... to give number 5.
I had thougt about subtract that are a library function and only get back white-characters. But the problem then is No way will give back 5 and not two words.
I thought about
filter([],L).
filter([X,Y|XS],[Y|XS]):- X = ' ',Y = ' ',L = [Y|XS], filter([Y|XS],L).
filter([X|XS],L):- filter(Xs,L).
That will remove white spaces and get back No way but it dosent work anbody have a tip.
Strings in Prolog are lists of character codes not of atoms, what explains why tests like X=' ' fail. See what is the result of executing
write("ab cd"), nl.
in your Prolog system.
You have errors in your 3 clauses:
What to do you expect the first clause to return in the last argument?
L is, as any other variable in a Prolog program, a variable that is local to the clause it appears in, never a global variable.
The second clause unifies L with a list and you use it as second argument of the recursive call: do you expect the recursive call to change the value of L? This will never be the case: in Prolog there is no assignment of variables, changes are made by building terms and unifying them with new variables.
What happens to X in your third clause???

Prolog beginner. How to take list as parameter and pass it on

I am a total beginner at Prolog. I am struggling with creating a rule, which takes a list as parameter and passes the list onto another rule. Here is my code:
combine([], '').
combine([L|List], Total) :-
combine(List, CombinedRest),
atom_concat(L, CombinedRest, Total).
findHeadline([W|Words], Combined) :-
combine(Words, Combined).
findHeadline2([Words], Combined) :-
combine(Words, Combined).
findHeadline works as expected, but findHeadline2 does not. Here is the output:
1 ?- findHeadline([billig, enkeltmand], Combination).
Combination = enkeltmand.
2 ?- findHeadline2([billig, enkeltmand], Combination).
false.
The output I was expecting from findHeadline was:
Combination = billigenkeltmand.
How can it be that this does not work?
I tried to utilize trace in SWI-prolog, but it gave me no clue whatsoever, as the findHeadline rule just exits immediately and does not call the combine rule at all.
It is not very clear what it is exactly that you are after. If you just want to concatenate a list of atoms to get one atom, use atomic_list_concat/2 available in SWI-Prolog:
?- atomic_list_concat([foo, bar, baz], C).
C = foobarbaz.
At the moment, your findHeadline2/2 reads:
"Take a list containing exactly one element, and combine/2 that element."
This is not what you are after, I have the feeling.
Your findHeadline/2, on the other hand, says:
"Take a list of at least one element, and combine/2 all elements except the first".
This is important: never ever ignore compilation warnings. You get code that does something, but you can be almost certain that it does not do what you want it to do, which is bad, or that if someone else reads your code, they will be confused, which is also bad.

Prolog Relational Tracking without Lists

I am trying to get a predicate to relate from 1 fact to another fact and to keep going until a specified stopping point.
For example,
let's say I am doing a logistics record where I want to know who got a package from who, and where did they get it from until the end.
Prolog Code
mailRoom(m).
gotFrom(annie,brock).
gotFrom(brock,cara).
gotFrom(cara,daniel).
gotFrom(daniel,m).
gotFrom(X,Y) :- gotFrom(Y,_).
So what I am trying to do with the predicate gotFrom is for it to recursively go down the list from what ever point you start (ex: gotFrom(brock,Who)) and get to the end which is specified by m, which is the mail room.
Unfortunately when I run this predicate, it reads out,
Who = annie.
Who = brock.
Who = cara.
etc.etc....
I tried stepping through the whole thing but Im not sure where it goes from brock to annie, to cara and all the way down till it cycles through trues for infinity. I have a feeling that it has something to do with the wildcard in the function (_), but Im not sure how else I could express that part of the function in order for the predicate to search for the next fact in the program instead of skipping to the end.
I tried using a backcut (!) in my program but it gives me the same error.
Any help is greatly appreciated. I don't want code I just want to know what I am doing wrong so I can learn how to do it right.
Thanks.
I'm afraid this rule is meaningless:
gotFrom(X,Y) :- gotFrom(Y,_).
There is nothing here to constrain X or Y to any particular values. Also, the presence of singleton variable X and the anonymous variable _ means that basically anything will work. Try it:
?- gotFrom([1,2,3], dogbert).
true ;
true ;
What I think you're trying to establish here is some kind of transitive property. In that case, what you want is probably more like this:
gotFrom(X,Z) :- gotFrom(X, Y), gotFrom(Y, Z).
This produces an interesting result:
?- gotFrom(brock, Who).
Who = cara ;
Who = daniel ;
Who = m ;
ERROR: Out of local stack
The reason for the problem may not be immediately obvious. It's that there is unchecked recursion happening twice in that rule. We recursively unify gotFrom/2 and then we recursively unify it again. It would be better to break this into two predicates so that one of them can be used non-recursively.
got_directly_from(annie,brock).
got_directly_from(brock,cara).
got_directly_from(cara,daniel).
got_directly_from(daniel,m).
gotFrom(X,Y) :- got_directly_from(X, Y).
gotFrom(X,Z) :- got_directly_from(X, Y), gotFrom(Y, Z).
This gives us the desired behavior:
?- gotFrom(brock, Who).
Who = cara ;
Who = daniel ;
Who = m ;
false.
Notice this one is resilient to my attack of meaningless data:
?- gotFrom([1,2,3], dogbert).
false.
Some general advice:
Never ignore singleton variable warnings. They are almost always a bug.
Never introduce a cut when you don't understand what's going on. The cut should be used only where you understand the behavior first and you understand how the cut will affect it. Ideally, you should try to restrict yourself to green cuts—cuts that only affect performance and have no observable effects. If you don't understand what Prolog is up to, adding a red cut is just going to make your problems more complex.

Resources