difference yap and swi-prolog reading canonical lists

swi prolog set
lists swi prolog
swi-prolog difference list
prolog element in list

I have the following test code trying to read file into a list

open('raw250-split1.pl', read, Stream),
read(Stream,train_xs(TrainXs)),
length(TrainXs, MaxTrain).

I will omit part of the output due to the file is quite large.

It works well with yap,

➜  chill git:(master) ✗ yap                                                      [18/06/19| 5:48PM]
% Restoring file /usr/lib/Yap/startup.yss
YAP 6.2.2 (x86_64-linux): Sat Sep 17 13:59:03 UTC 2016
   ?- open('raw250-split1.pl', read, Stream),                                                           
      read(Stream, train_xs(TrainXs)),                                                                     
      length(TrainXs, MaxTrain).
MaxTrain = 225,
Stream = '$stream'(3),
TrainXs = [[parse([which,rivers,run,through,states,bordering,new,mexico,/],answer(_A,(river(_A),traverse(_A,_B),next_to(_B,_C),const(_C,stateid('new mexico')))))],
<omited output>
,[parse([what,is,the,largest,state,capital,in,population,?],answer(_ST,largest(_SU,(capital(_ST),population(_ST,_SU)))))]]

But on swi-prolog, it will produce Type error

➜  chill git:(master) ✗ swipl                                                     [18/06/19| 7:24PM]
Welcome to SWI-Prolog (threaded, 64 bits, version 7.6.4)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit http://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).

?- open('raw250-split1.pl', read, Stream),    
   read(Stream, train_xs(TrainXs)),                                                                     
   length(TrainXs, MaxTrain).
ERROR: raw250-split1.pl:4:
    Type error: `list' expected, found `parse(which.(rivers.(run.(through.(states.(bordering.(new.(mexico.((/).[])))))))),
    <omited output>
,answer(_67604,(state(_67604),next_to(_67604,_67628),const(_67628,stateid(kentucky))))).[].(parse(what.((is).(the.(largest.(state.(capital.(in.(population.((?).[])))))))),answer(_67714,largest(_67720,(capital(_67714),population(_67714,_67720))))).[].[]))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))' (a compound)
    In:
      [10] throw(error(type_error(list,...),context(...,_67800)))
       [7] <user>

    Note: some frames are missing due to last-call optimization.
    Re-run your program in debug mode (:- debug.) to get more detail.

What might be the problem for the error here?

File raw250-split1.pl can be found from the ftp url below, if you'd like to try it.

Thank you for the help!


I am trying to migrate an earlier code to SWI-Prolog, which was written in SICStus 3 #3: Thu Sep 12 09:54:27 CDT 1996 or earlier by Raymond J. Mooney ftp://ftp.cs.utexas.edu/pub/mooney/chill/. All the questions with this tag are all related to this task. I'm new to prolog, helps and suggestions are welcomed!

The raw250-split1.pl was apparently written using canonical notation. The traditional list functor is ./2 but SWI-Prolog 7.x changed it to '[|]'/2 in order to use ./2 for other purposes. This results in the the variable TrainXs being instantiated by the read/2 call to a compound term whose argument is not a list:

?- open('raw250-split1.pl', read, Stream), read(Stream,train_xs(TrainXs)).
Stream = <stream>(0x7f8975e08e90),
TrainXs = parse(which.(rivers.(run.(through.(states.(bordering.(... . ...)))))), answer(_94,  (river(_94), traverse(_94, _100), next_to(_100, _106), const(_106, stateid('new mexico'))))).[].(parse(what.((is).(the.(highest.(point.(... . ...))))), answer(_206,  (high_point(_204, _206), const(_204, stateid(montana))))).[].(parse(what.((is).(the.(most.(... . ...)))), answer(_298, largest(_300,  (population(_298, _300), state(...), ..., ...)))).[].(parse(through.(which.(states.(... . ...))), answer(_414,  (state(_414), const(..., ...), traverse(..., ...)))).[].(parse(what.((is).(... . ...)), answer(_500, longest(_500, river(...)))).[].(parse(how.(... . ...), answer(_566,  (..., ...))).[].(parse(... . ..., answer(..., ...)).[].(parse(..., ...).[].(... . ... .(... . ...))))))))).

YAP still uses the ./2 functor for lists, which explains why it can handle it. A workaround for SWI-Prolog is to start it with the --traditional command-line option:

$ swipl --traditional
...
?- open('raw250-split1.pl', read, Stream), read(Stream,train_xs(TrainXs)).
Stream = <stream>(0x7faeb2f77700),
TrainXs = [[parse([which, rivers, run, through, states, bordering|...], answer(_94,  (river(_94), traverse(_94, _100), next_to(_100, _106), const(_106, stateid('new mexico')))))], [parse([what, is, the, highest, point|...], answer(_206,  (high_point(_204, _206), const(_204, stateid(montana)))))], [parse([what, is, the, most|...], answer(_298, largest(_300,  (population(_298, _300), state(...), ..., ...))))], [parse([through, which, states|...], answer(_414,  (state(_414), const(..., ...), traverse(..., ...))))], [parse([what, is|...], answer(_500, longest(_500, river(...))))], [parse([how|...], answer(_566,  (..., ...)))], [parse([...|...], answer(..., ...))], [parse(..., ...)], [...]|...].

The type error you get is due to the length/2 expecting a list when the first argument is bound.

Different results in swi-prolog and yap, Different results in swi-prolog and yap swipl returns 92; while yap returns 40320. Also difference yap and swi-prolog reading canonical lists. Is true when Difference is the symmetric difference of Set1 and Set2. I.e., Difference contains all elements that are not in the intersection of Set1 and Set2 . The semantics is the same as the sequence below (but the actual implementation requires only a single scan).

There is a tilde as last character in that file, causing the syntax being invalid, so you should remove it before reading. I don't know why YAP accept the file as valid, should raise an error AFAIK.

[PDF] SWI-Prolog version 7 extensions, It is not possible to distinguish (at run time) a list of integers or atoms from a string​. Sometimes This provides fast access, but uses a lot of space while the structures are hard to write and read. Prolog, Amzi! and YAP. ECLiPSe [6] and represented by a canonical term, which implies that two dicts that represent the same. SWI-Prolog implements both Edinburgh and ISO representations for non-decimal numbers. According to Edinburgh syntax, such numbers are written as < radix >’< number > , where < radix > is a number between 2 and 36.

There is a read option dotlists/2 in SWI-Prolog:

dotlists(Bool) If true (default false), read .(a,[]) as a list, even if lists are internally nor constructed using the dot as functor. This is primarily intended to read the output from write_canonical/1 from other Prolog systems. See section 5.1. http://www.swi-prolog.org/pldoc/man?predicate=read_term/2

This gives you the desired result, without changing the mode:

Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.0)

?- read_term(X, [dotlists(true)]).
|: .(a,.(b,.(c,[]))).
X = [a, b, c].

SWI-Prolog future directions, Definition of error handling Defining that this predicate is non-deterministic if List is a partial list and Len is unbound is necessary. It even disallows systems to reject goals like Len is A+B, length(Len, List) based on static analysis. YAP and SWI-Prolog have a similar drive, where YAP concentrates on performance and  Difference list version of PL_unify_wchars(), only supporting the types PL_CODE_LIST and PL_CHAR_LIST. It serves two purposes. It allows for returning very long lists from data read from a stream without the need for a resizing buffer in C. Also, the use of difference lists is often practical for further processing in Prolog.

SWI-Prolog -- Manual, library(readutil): Read utilities · library(record): Access named fields in a term · library(registry): Manipulating the Windows As both are canonical sorted lists, this is the same as ==/2. Difference ): Intersection and difference between two ordered sets. author: Copied from YAP, probably originally by Richard O'Keefe. SWI-Prolog provides many extensions to the set of floating point functions defined by the ISO standard. The current policy is to provide such functions on‘as-needed' basis if the function is widely supported elsewhere and notably if it is part of the C99 mathematical library. In addition, we try to maintain compatibility with YAP. [ISO]-+Expr

SWI-Prolog -- format/2, format( +Format, :Arguments ): Format is an atom, list of character codes, or a Prolog string. Same as d, but makes large values easier to read by inserting a comma every three digits left Give the next argument to write_canonical/1. n This option is not present in the original definition by Quintus, but supported by some  Similar to functor/3, but deals with SWI-Prolog's zero-argument callable terms and avoids creating a non-callable term if Name is not an atom and Arity is zero. is_control_goal/1 True if Goal is a compiled Prolog control structure.

[PDF] VU University Amsterdam University of Amsterdam , dard it is largely compatible to Quintus, SICStus and YAP Prolog. 4.5 List the program, predicates or clauses . Some applications use the Prolog read/1 predicate for data via side-channels such as differences in the duration of successive instructions. An File is a canonical filename or a file indicator that is valid for. SWI-Prolog streams are, compatible with the ISO standard, either input or output streams. To accommodate portability to other systems, a pair of streams can be packed into a stream-pair. See stream_pair/3 for details. SWI-Prolog stream handles are unique symbols that have no syntactical representation.

Comments
  • Consider to use SICStus 4: It has an incredibly fast JIT-compiler
  • @false Thanks! Our school doesn't have the license. I installed one for evaluation. Just have to reapply for another one when it expires.
  • The current version of SWI can parse and highlight that source without problems. Now I'll try read/2 as well.
  • Thank both of you! It seems compatibility is a real challenge when learning prolog.
  • I can confirm read/2 works as well, and the problem is indeed the tilde at EOF
  • The migration to yap can run but with error now, it seems more work to be done on swi-prolog. Thanks for the help!
  • @CapelliC On my machine, adding --traditional can also work with that tilde.
  • I tried to remove that tilde, but the error persists.
  • Yes, I overlooked that, but it's most probably irrelevant. Are you sure you removed the tilde from the file actually read ?
  • I double checked that with tail, )))))))))..