Prolog error: "expected stream, but found '$stream' ..." - stream

I am working on a program for a college assignment, currently I'm trying to write some denials from an abductive procedure written on a file as integrity constraints, but I'm having some problems.
My predicates for the task look like this:
append_denials(_, []).
append_denials(File, [fail(_, Den)|Tail]) :-
open(File, append, Stream),
write(Stream, 'ic :- '),
write_denials(Stream, Den),
write(Stream, '.'),
nl(Stream),
close(Stream),
append_denials(File, Tail).
write_denials(Stream, [T]) :-
write(Stream, T).
write_denials(Stream, [H|T]) :-
write(Stream, H),
write(Stream, ', '),
write_denials(Stream, T).
And they are queried with something along these lines:
append_denials('denyagain.txt', [fail([_C],[battery_flat(_C),lights_go_on(_C)]),fail([_D],[has_no_fuel(_D),\+fuel_indicator_empty(_D),\+broken_indicator(_D)])]).
The problem is that they seem to work if I put them on a separate file (with these predicates and nothing else), but when used within the program (3000 lines of Prolog that I can't post here...) I get this error:
! Domain error in argument 1 of write/2
! expected stream, but found '$stream'(139681177337584)
! goal: write('$stream'(139681177337584),\+broken_indicator(_116))
% source_info
I checked and I can confirm that the predicates are not being overwritten... I really don't understand how this could be happening.
Any suggestion or clues regarding where I might be going wrong would be very welcome!
Many thanks,
David.

Related

Tests: check if tuple is returned

I am writing a test which checks response from gen_server. The response itself is either {profile, SomeProfileFromGenServer} or {error, ErrorResponse}
So I wanted to write a test which does:
Profile = mygenserver:get_profile(),
?assertEqual(Profile, {profile, SomeProfile})
As I don't really care about the SomeProfile value. But this says that SomeProfile is unbound :( Is there a way to fix it?
You can use ?assertMatch, with the first argument being a pattern:
?assertMatch({profile, _}, Profile)
assertMatch(GuardedPattern, Expr)
Evaluates Expr and matches the result against GuardedPattern, if testing is enabled. If the match fails, an informative exception will be generated; see the assert macro for further details. GuardedPattern can be anything that you can write on the left hand side of the -> symbol in a case-clause, except that it cannot contain comma-separated guard tests.
The main reason for using assertMatch also for simple matches, instead of matching with =, is that it produces more detailed error messages.
Examples:
?assertMatch({found, {fred, _}}, lookup(bloggs, Table))
?assertMatch([X|_] when X > 0, binary_to_list(B))

Expected rel[loc,loc] (...), but got rel[loc,loc], what does rel[loc,loc](...) mean?

I just tested my code to build the dot diagram, when I tried to union two relations together and passed the the sumed up relation, following error is reported:
Expected rel[loc,loc] (...), but got rel[loc,loc]
I am not sure what relloc, loc means because each of the separated relations works correctly. Could please you tell me why?
Yes, that message can be confusing!
rel[loc,loc] (...) means a type of function which returns a rel[loc,loc] given some arguments ... which are unspecified in this message
rel[loc,loc] is just the type of a binary relation of loc
We sometimes see this kind of message occurring when ( ) brackets are used accidentally instead of [ ] for indexing into a relation. If you provide a little more context code, maybe we can diagnose the issue from that more precisely.

why erlang not supporting expressions like : mysum(32)(1)

I am new in Eralng . get a little query about applying functions
assumming got a funciton defined :
mysum(X) -> fun(Y)-> X + Y end.
then try to calling like this
mysum(32)(332)
getting error
* 1: syntax error before: '('
so I had to
apply(mysum(32),[333])
or
M = mysum(32), M(333)
but I would like to know a little bit more , why it is not supporting , what is the disadvantage
As you expected, mysum return a function. you must enclose the evaluation inside parenthesis to satisfy the erlang parser:
(mysum(32))(332)
this spelling is obviously not ambiguous.
Your expression seems not ambiguous because you know that mysum(32) is a function, but the types are solved at run time in erlang, so the parser has no idea of what is mysum(32), it is expecting some help here to know what it has to do: the parenthesis, the apply or the intermediate variables, but it could be an operator or a separator.

no match of right hand side value

I'm reading the "Seven Languages in Seven Weeks" book, and can't pass a little issue in the day one erlang's self-study.
My code is something like this:
-module(slsw).
-export([count_words/1]).
list_length([]) -> 0;
list_length(String) ->
[_ | Tail] = String,
1 + list_length(Tail).
count_words(Text) ->
{_, R} = re:split(Text, " "),
list_length(R).
But, when I open erl, compile it (c(slsw).), and try to use it with something like this:
slsw:count_words("yoo dude, this is a test").
I got this annoying runtime exception:
** exception error: no match of right hand side value [<<"yoo">>,<<"dude,">>,<<"this">>,<<"is">>,<<"a">>,
<<"test">>]
in function slsw:count_words/1 (slsw.erl, line 19)
Looks like it end the array, then throw this exception.. what am I doing wrong?
I also found the string:words function, but I want to do my own for fun/study.
Thanks in advance
re:split/2 just returns a list, instead of a tuple. It may be a typo in the Book's text.
Admittedly, Erlang error messages can be a tad cryptic to folks new to the language, but the hint that can help you read the error message is that it's saying the right hand side of the equals sign evaluates to [<<"yoo">>,<<"dude,">>,<<"this">>,<<"is">>,<<"a">>,<<"test">>] (simply the return value from re:split - ie, a list of binaries), and it's unable to match that with the 2-tuple on the left.
So if you simply changed your count_words function to the following, that should be sufficient:
count_words(Text) ->
R = re:split(Text, " "),
list_length(R).
I don't believe re:split/2 returns a tuple - it returns a list. So, your {_, R} = re:split/2 two line errors out because the return of the function cannot match the tuple on the left hand side of the =

Input in Prolog

I'm currently working on a recursive Prolog program to link routes together to create a basic GPS of the Birmingham area. At the moment I can get output as so:
Input
routeplan(selly_oak, aston, P).
Output
P = [selly_oak, edgbaston, ... , aston]
What I would like to do is have my program provide some sort of interface, so if I were to type in something along the lines of:
Route from selly_oak to aston
It would provide me with:
Go from selly_oak to edgbaston
Go from edgbaston to ...
Finally, Go from ... to aston.
Prolog is a powerful language so I assume this is easily possible, however many of the books I've taken out seem to skip over this part. As far as I am aware I have to use something along the lines of write() and read() although the details are unknown to me.
Could anyone here a Prolog novice out with some basic examples or links to further information?
EDIT: A lot of these answers seem very complicated, where the solution should only be around 5-10 lines of code. Reading in a value isn't a problem as I can do something along the lines of:
find:-
write('Where are you? '),
read(X),
nl, write('Where do you want to go? '),
read(Y),
loopForRoute(X,Y).
I'd prefer it if the output could be written out using write() so a new line (nl) can be used, so that it displays like the output above.
If this were my input, how would I then arrange the top routeplan() to work with these inputs? Also, if I were to add the Lines for these stations as an extra parameter how would this then be implemented? All links are defined at the beginning of the file like so:
rlinks(selly_oak, edgbaston, uob_line).
rlinks(edgbaston, bham_new_street, main_line).
Therefore, with this information, it'd be good to be able to read the line as so.
Go from selly_oak to edgbaston using the uob_line
Go from edgbaston to ... using the ...
Finally, go from ... to aston using the astuni_line
A book which discusses such things in detail is Natural Language Processing for Prolog Programmers
by Michael A. Covington.
In general, what you need to do is
Tokenize the input
Parse the tokens (e.g. with DCG) to get the input for routeplan/3
Call routeplan/3
Generate some English on the basis of the output of routeplan/3
Something like this (works in SWI-Prolog):
% Usage example:
%
% ?- query_to_response('Route from selly_oak to aston', Response).
%
% Response = 'go from selly_oak to edgbaston then go from edgbaston
% to aston then stop .'
%
query_to_response(Query, Response) :-
concat_atom(QueryTokens, ' ', Query), % simple tokenizer
query(path(From, To), QueryTokens, []),
routeplan(From, To, Plan),
response(Plan, EnglishTokens, []),
concat_atom(EnglishTokens, ' ', Response).
% Query parser
query(path(From, To)) --> ['Route'], from(From), to(To).
from(From) --> [from], [From], { placename(From) }.
to(To) --> [to], [To], { placename(To) }.
% Response generator
response([_]) --> [stop], [.].
response([From, To | Tail]) -->
goto(path(From, To)), [then], response([To | Tail]).
goto(path(From, To)) --> [go], from(From), to(To).
% Placenames
placename(selly_oak).
placename(aston).
placename(edgbaston).
% Mock routeplan/3
routeplan(selly_oak, aston, [selly_oak, edgbaston, aston]).
Hm, if I understand you correctly you just want to format the list nicely for printing out, no?
In SWI-Prolog this works:
output_string([A,B],StrIn,StrOut) :-
concat_atom([StrIn, 'Finally, Go from ', A, ' to ', B, '.'],StrOut),
write(StrOut).
output_string([A,B|Rest],StrIn,StrOut) :-
concat_atom([StrIn,'Go from ', A, ' to ', B, '.\n'],StrAB),
output_string([B|Rest],StrAB,StrOut).
then call with
output_string(P,'',_).
It's probably not very efficient, but it does the job. :)
For this sort of thing, I usually create shell predicates. So in your case...
guided:-
print('Enter your start point'),nl,
read(Start),
print('Enter your destination'),nl,
read(Dest),
routeplan(Start, Dest, Route),
print_route(Route).
And print_route/1 could be something recursive like this:
print_route([]).
print_route([[A,B,Method]|Tail]):-
print_route(Tail),
print('Go from '), print(A),
print(' to '), print(B),
print(' by '), print(Method), nl.
I've assumed that the 3rd variable of the routeplan/3 predicate is a list of lists. Also that it's built by adding to the tail. If it's not, it should be fairly easy to adapt. Ask in the comments.
Here are a few predicates to read lines from a file/stream into a Prolog string:
%%% get_line(S, CL): CL is the string read up to the end of the line from S.
%%% If reading past end of file, returns 'end_of_file' in CL first, raises
%%% an exception second time.
%%% :- pred get_string(+stream, -list(int)).
get_line(S, CL) :-
peek_code(S, C),
( C = -1
-> get_code(S, _),
CL = end_of_file
; get_line(S, C, CL)).
get_line(_, -1, CL) :- !, CL = []. % leave end of file mark on stream
get_line(S, 0'\n, CL) :- !,
get_code(S, _),
CL = [].
get_line(S, C, [C|CL]) :-
get_code(S, _),
peek_code(S, NC),
get_line(S, NC, CL).
%% read_lines(L): reads lines from current input to L. L is a list of list
%% of character codes, newline characters are not included.
%% :- pred read_lines(-list(list(char))).
read_lines(L) :-
current_input(In),
get_line(In, L0),
read_lines(In, L0, L).
%% read_lines(F, L): reads lines from F to L. L is a list of list of character
%% codes, newline characters are not included.
%% :- pred read_lines(+atom, -list(list(char))).
read_lines(F, L) :-
fail_on_error(open(F, read, S)),
call_cleanup((get_line(S, L0),
read_lines(S, L0, L)),
close(S)).
read_lines(_, end_of_file, L) :- !, L = [].
read_lines(S, H, [H|T]) :-
get_line(S, NH),
read_lines(S, NH, T).
Then, take a look at DCGs for information on how to parse a string.

Resources