Daimeku
Daimeku

Reputation: 13

reading lines into lists with prolog

I have a text file with some information, each line is a list of values. I want to read each line and store it in a list with all the other lines. This is the code I have so far

getLines:-
      open('textFile.abc', read, Source),
      readData(Source,DataList),
      write(DataList).

readData(Source,DataList):-
                    read(Source,NewLine),
                    NewLine== end_of_file -> fail;true,
                    readData(Source,[DataList|NewLine]).

readData(Source,[DataList|end_of_file]).

this is the text file 'textfile.abc'

[0.45,20,850,900,3].
[0.45,20,850,900,2].
[0.45,20,850,900,1].

When I run getLines it executes and writes '_G1147068' instead of the list of items. I'm not sure what I'm doing wrong here, any help would be appreciated.

Upvotes: 1

Views: 3753

Answers (1)

Wouter Beek
Wouter Beek

Reputation: 3407

The main reason why your code does not work the way you intend it to is found in the second clause of readData/2 (quoted below). It contains two singleton variables and [DataList|end_of_file] is not a list (since end_of_file is an atom).

readData(Source,[DataList|end_of_file]).

Your code can be improved in other ways as well:

  • You open a stream but you never close it: you can use close/1 for this.
  • Even if you close the stream after readData/2 succeeds, suppose your program throws an exception or fails while running readData/2. Now close/1 will not be reached and the stream will still be open. Luckily, there is setup_call_cleanup/3 which closes the stream even if your code fails / throws an exception.
  • Since the data you are reading happens to be Prolog terms, you can use read_term/3 which comes with many nice options.
  • Notice that in list construction L = [H|T] I make sure the T is always a list.

Resulting code:

getLines(L):-
  setup_call_cleanup(
    open('textFile.abc', read, In),
    readData(In, L),
    close(In)
  ).

readData(In, L):-
  read_term(In, H, []),
  (   H == end_of_file
  ->  L = []
  ;   L = [H|T],
      readData(In,T)
  ).

Hope this helps you out!

Upvotes: 1

Related Questions