1

Is there a way to know what type is a variable in Prolog? I have the code

test:- 
    writeln('Please enter the absolut file name :'),
    read(FileName),
    write('Opening file '),
    write(FileName),nl,
    open(FileName,read,Stream),
    read_file(Stream,Lines),
    close(Stream),
    parseLines(Lines).


% used on reading the text file 
read_file(Stream,[]) :-
    at_end_of_stream(Stream).
% used on reading the text file 
read_file(Stream,[X|L]) :-
    \+ at_end_of_stream(Stream),
    read(Stream,X),
    read_file(Stream,L).

parseLines(Lines):-
%primele 2 linii contin lista cu barbatii si list cu femeile iar 
%restul liniilor contin preferintele acestora
    Lines=[LB|[LF|LPrefs]],
    writeln(LB),
    atom_length(LB,2).

And I get the error (when running test)

ERROR: [Thread pdt_console_client_0_Default Process] atom_length/2: Type error: `list' expected, found `man([m1,m2])'

The input text file contains

man = {m1, m2}.
women = {w1, w2}.

m1: w1 > w2.
m2: w1 > w2.
w1: m1 > m2.
w2: m1 > m2.

I am trying to parse that file but anything I try I get that error, like the things in the Lines read from the file are not string,atoms , I have no idea what to do to fix this.

P.S.Any idea on how to fast/simple parse the file? It feels strange that parsing the input for the problem is much harder then solving the problem.

Thanks.

Edit: I found the compound predicate and the line read from files is a compound term. Edit2: My goal is to read the data in that file and assert it or similar, I want to solve the stable marriage problem, I solve it but I can't figure out this part of reading the input from this file format.

Edit3: I have other input files that have lines like:

alan: christine > tina > zoe > ruth > sarah.

and this lines fail when trying to read them as terms with read_file_to_terms because of the multiple > operators, so I think not all my inputs are valid Prolog

false
  • 10,264
  • 13
  • 101
  • 209
simion314
  • 1,394
  • 16
  • 29
  • I'm sure you've got a real question here, but it needs a bit of restatement. Prolog variables per se are untyped: they can bind to any Prolog term (value). Your issue seems to be getting error messages from calling built-in predicates with variables bound to wrong value types, perhaps an atom where a string is expected. Generally you can resolve these by reading the file in a more specialized way, or by converting the terms you get now to required types. – hardmath Jan 08 '13 at 15:56
  • Duplicate? http://stackoverflow.com/questions/3864382/prolog-type-checking – NotAUser Jan 08 '13 at 15:57
  • Also, referring to your last statement: that is very true. My question is: why would you use Prolog to parse a file? Use the power of the language when you need it. Parse it with Python and then use Prolog for the meaty bits :). – NotAUser Jan 08 '13 at 15:59
  • add a description of what `parseLines(Lines)` should do. – CapelliC Jan 08 '13 at 17:00
  • The crux of your problem is to define what you expect to do with the input. I'm suspecting that the goal is implementing bipartite matching like [Stable Marriage Problem](http://en.wikipedia.org/wiki/Stable_marriage_problem), and if so you need to give some thought as to how bipartite graphs should be represented. With that as an endpoint, you can work on parsing the input file and analyzing how the data fits the representation. – hardmath Jan 08 '13 at 20:01

1 Answers1

2

Since you tagged your question [swi-prolog], and your file contains valid Prolog terms, you could use read_file_to_terms/3, and load the list in a single call (this hint is for P.S. part). After that you must process your terms' list: your parseLines/1 it's useless. Just as example of list processing, I'll display each loaded term:

?- read_file_to_terms('/home/carlo/x.txt',L,[]), maplist(writeln, L).
man={m1,m2}
women={w1,w2}
m1:w1>w2
m2:w1>w2
w1:m1>m2
w2:m1>m2
L = [man={m1, m2}, women={w1, w2}, m1:w1>w2, m2:w1>w2, w1:m1>m2, w2:m1>m2].

edit I think {} is named 'set constructor', it's just a weird shape for a compound:

?- write_canonical({a,b,c}).
{}(','(a,','(b,c)))

you can use univ to get the list of arguments

?- {a,b,c} =.. X.
X = [{}, (a, b, c)].

bug in previous edit

=.. seems of little relevance, because more than a compound, {} resembles an operator, both prefix and postfix (i.e. combining in some way op(xf,,({)) and op(fx,,(}))).

AFAIK converting 'the set' to a list requires something like

setcons_to_list(S, L) :-
    S =.. [{}, E] -> andexpr_to_list(E, L) ; L = [].

andexpr_to_list((E,Es), [E|Ts]) :-
    !, andexpr_to_list(Es, Ts).
andexpr_to_list(E, [E]).

test

?- setcons_to_list({},L).
L = [].

?- setcons_to_list({1,2,3,4},L).
L = [1, 2, 3, 4].

more edit

Prolog operators are 'configurable', it's possible to instruct the parser about that preference list. Add an op declaration in your source :- op(10,xfy,(>)).. Here a sample using the prompt

?- op(10,xfy,(>)).
true.

?- X = (alan: christine > tina > zoe > ruth > sarah),write_canonical(X).
:(alan,>(christine,>(tina,>(zoe,>(ruth,sarah)))))
X = alan:christine>tina>zoe>ruth>sarah.

beware: changing the predefined associativity should be done with care. Otherwise, this other answer could be useful if you prefer to craft a more general parser, using DCGs.

Community
  • 1
  • 1
CapelliC
  • 59,646
  • 5
  • 47
  • 90
  • Thx, this is great, but I have a question, so I get in the list L the first element man={m1,m2} ,it seems this is a compound term, is this something like =(man, {m1,m2}) ? and what about {} braces, i did not know that {} is used in prolog, can you point me in the right direction on learning how to load this terms in my application. – simion314 Jan 08 '13 at 17:09
  • Thxm, one more issue, I have other input file that fails to load with read_file_to_terms, see also my last edit. – simion314 Jan 08 '13 at 19:58
  • 1
    I've added some syntax details, HTH – CapelliC Jan 08 '13 at 20:40