List of lists into modified single list

2019-08-02 10:09发布

问题:

These are predicates which reads from input file

read_line(L,C) :-
    get_char(C),
    (isEOFEOL(C), L = [], !;
        read_line(LL,_),% atom_codes(C,[Cd]),
        [C|LL] = L).

%Tests if character is EOF or LF.
isEOFEOL(C) :-
    C == end_of_file;
    (char_code(C,Code), Code==10).

read_lines(Ls) :-
    read_line(L,C),
    ( C == end_of_file, Ls = [] ;
      read_lines(LLs), Ls = [L|LLs]
    ).

Input file:

A B
C D
E F
G H

read_lines(L) returns L = [[A, ,B],[C, ,D],[E, ,F],[G, ,H]]. My goal is to replace all the spaces and merge list of lists into single list. So expected output should look like: L = [A-B,C-D,E-F,G-H]. What I got so far is modified read_line function:

read_line(L,C) :-
    get_char(C),
    ( (char_code(C,Code), Code == 32)
        -> C = '-'
        ; C = C),
    (isEOFEOL(C), L = [], !;
        read_line(LL,_),% atom_codes(C,[Cd]),
        [C|LL] = L).

When I use it, Prolog says Syntax error: Unexpected end of file. What's wrong with that?

回答1:

The problem is in this code:

( (char_code(C,Code), Code == 32)
    -> C = '-'
    ; C = C),

If a space character was read into variable C, char_code binds Code to 32, and the condition is true. Then Prolog tries to unify C with '-', but C is already bound to ' '! This fails, so your read_line call fails and leaves some unconsumed input on the standard input stream. The next time Prolog tries to read input from you, it actually reads that remaining input.

The underlying cause of the problem is that you seem to be trying to "reassign" the variable C. That is not possible in Prolog; once a variable is bound, it can only become unbound on backtracking.

Use a new variable, something like this:

( (char_code(C,Code), Code == 32)
    -> NewC = '-'
    ; NewC = C),

with corresponding uses of NewC where appropriate.



标签: prolog