Path: utzoo!mnetor!uunet!mcvax!unido!ecrcvax!micha From: micha@ecrcvax.UUCP (Micha Meier) Newsgroups: comp.lang.prolog Subject: Re: behavior of read/get0 at end_of_file Message-ID: <522@ecrcvax.UUCP> Date: 7 Apr 88 12:44:16 GMT References: <608> <1197@kulcs.kulcs.uucp> <783@cresswell.quintus.UUCP> <518@ecrcvax.UUCP> <801@cresswell.quintus.UUCP> <243@gould.doc.ic.ac.uk> Reply-To: micha@ecrcvax.UUCP (Micha Meier) Organization: ECRC, Munich 81, West Germany Lines: 103 Keywords: get0, repeat, debugging In article <243@gould.doc.ic.ac.uk> cdsm@doc.ic.ac.uk (Chris Moss) writes: >... I personally think "repeat" should >be left out of the standard (there's no penalty overhead in not having it >built-in these days anyway). Don't other people have my problem? Unfortunately, there is a penalty when it is not built-in. If repeat/0 is coded as repeat. repeat :- repeat. it creates a new choice point each time the system backtracks to it, however this is not the main point, I'm sure there are clever compilers around that could get by with it. The problem concerns the Byrd box model for debugging and it was pointed to me by Thomas Graf: if repeat/0 is built-in, it is called only once (it enters the CALL port and leaves through the EXIT port), on backtracking it enters by REDO and leaves by EXIT. When its choice point is cut, it just exits or fails. The situation is different with the above Prolog coding: on each backtracking to repeat/0 a new call is made, i.e. a new box and hence there are two more ports to trace. Look at this script from SICStus Prolog: | ?- [user]. | repeat1. | repeat1 :- repeat1. | ^D yes | ?- trace, repeat1, fail. The debugger will first creep -- showing everything (trace). 1 1 Call: repeat1 ? 1 1 Exit: repeat1 ? 2 1 Call: fail ? 2 1 Fail: fail ? 1 1 Redo: repeat1 ? 2 2 Call: repeat1 ? 2 2 Exit: repeat1 ? 1 1 Exit: repeat1 ? 3 1 Call: fail ? 3 1 Fail: fail ? 1 1 Redo: repeat1 ? 2 2 Redo: repeat1 ? 3 3 Call: repeat1 ? 3 3 Exit: repeat1 ? 2 2 Exit: repeat1 ? 1 1 Exit: repeat1 ? 4 1 Call: fail ? etc., while the built-in repeat/0 behaves normally: | ?- repeat, fail. 1 1 Call: repeat ? 1 1 Exit: repeat ? 2 1 Call: fail ? 2 1 Fail: fail ? 1 1 Redo: repeat ? 1 1 Exit: repeat ? 2 1 Call: fail ? 2 1 Fail: fail ? 1 1 Redo: repeat ? 1 1 Exit: repeat ? 2 1 Call: fail ? You can say that it is possible to skip over the multiple 'repeat' ports, but the point is, that the stack space for them is needed even when they are not printed - you cannot run such a repeat/0 forever, eventually it is going to overflow some stack. On the other hand, we could ask whether the box model is right in this case - after all it does not bring any new information by repeating all these ports. There is no reasonable argument to force people to use tail-recursive loops instead of repeat-fail loops; if I'm using temporary structures and I know that with the recursive loops they are going to be garbage collected whereas with repeat-fail loops they are just popped, I will always prefer the latter and the standard should support me by providing a built-in repeat/0, since its full functionality cannot be provided by other means. --- Another point I want to make concerns the -1 returned by get0/1 at eof: several people have claimed that it is portable and that it cannot be confused with any character, however it is *not* portable, since it relies on the fact that no valid character can be confused with -1. If characters are represented as strings of length 1, then -1 has a different type and so there is no confusion, but the eof value should have the same type (if nothing else then because of indexing). If characters are integers, taking -1 implies that no character can have the code 2^n - 1 (n being the number of bits on which the character is stored) which is not necessarily true - you can use 7 bits for ASCII, 16 bits for Kanji and anything else on any number of bits. Only if we waste enough space we can guarantee that -1 will be different. A standard that forces you to waste space would really not be good. --Micha