restivo@POLYA.STANFORD.EDU (Chuck Restivo) (05/01/88)
Date: Fri 29 Apr 1988 04:33-PST >From: Chuck Restivo (The Moderator) <PROLOG-REQUEST@POLYA.STANFORD.EDU> Reply-to: PROLOG@POLYA.STANFORD.EDU> US-Mail: P.O. Box 4584, Stanford CA 94305 Subject: PROLOG Digest V6 #24 To: PROLOG@POLYA.STANFORD.EDU PROLOG Digest Friday, 29 Apr 1988 Volume 6 : Issue 24 Today's Topics: Announcement - User's Group, Implementation - Constraint Satisfaction & Code Formatting, & Destructive Predicates & BSI Standards & Additional Predicates --------------------------------------------------------------------------------------------------------------------------- Date: 13 Mar 88 22:04:26 GMT >From: lagache@violet.Berkeley.EDU (Edouard Lagache) Organization: University of California, Berkeley Subject: A users group for people interested in PROLOG A PROLOG Users Group Forming While interest in PROLOG has been on the increase throughout the world, most users remain isolated. While facilities like the PROLOG SIG on the ARPAnet provide some interaction between users, there are times when a more unified approach would be desirable. Thus a number of persons interested in PROLOG have formed "the PROLOG Forum": a users group for those programming in PROLOG or interested about PROLOG. We are open to all users of PROLOG no matter what their skill level or background. This group was formed to achieve the following objectives: 1.) Provide an environment for PROLOG users to interact and learn from each other. 2.) Provide a forum for the PROLOG industry to present their wares and to get feedback from the user community. 3.) Encourage the use of PROLOG where it appropriate and to educate the Artificial Intelligence and Software Development communities about PROLOG and its strong and weak points. 4.) Support the further development of the PROLOG language in such areas as encouraging efforts toward a PROLOG standard. 5.) Providing a medium for the PROLOG user community to make their feelings known about issues that effect them. While we are based in the San Francisco Bay Area, we are open to anyone, and we plan to distribute our newsletter all over the world. We will be distributing complementary issues of our first newsletter in a few weeks. Anyone wishing to obtain a copy is encouraged to contact the PROLOG Forum either by electronic mail 'lagache@violet.berkeley.edu', or by telephone: (415) 642-9920 Monday and Tuesdays (10 to 4 Pacific Standard time). (415) 631-0183 Thursday and Friday workdays, and all evenings. Of the sake of my own sanity, replies by e-mail would be prefered whenever possible. -- Edouard Lagache ------------------------------- Date: 13 Mar 88 22:12:08 GMT >From: lagache@violet.Berkeley.EDU (Edouard Lagache) Subject: Minutes of the PROLOG Forum meeting of 3/10/88 MINUTES OF THE PROLOG FORUM MEETING OF 3/10/1988 The PROLOG Forum meeting of March 10, was still an informal organizational meeting. The members present reviewed a draft of the first issue of the newsletter. We hope to begin distributing in a few weeks. We elected the following officers: President and Newsletter editor: Mark Epperson Treasurer: Dave Kuhlman Staff writer: Edouard Lagache While not officially honored, Steve Engle has been serving as Software librarian. We set the dues for membership at $25 for those within United States mailing areas, and $35 dollars for international members. Membership will basically represent a subscription to the PROLOG forum newsletter. It may also include privileged access to the group's PROLOG software library, but those details have not yet been worked out. The balance of the meeting was devoted to examining two programs by Edouard Lagache. The first program was a first attempt at building a "consultant" program for PROLOG programmers. The program presented was basically a variation on the "Eliza" program that instead of merely trying to find any appropriate response would attempt to query the user to solve the problem by his/herself. This is done by asking the user questions that encourage reflection on her/his own problem solving processes. While the program was a rather crude effort at best, it may still be quite useful as a "fall back" system for a more intelligent consultant. Since it will always come up with some sort of reply, it could be used to help coax the user to come up with enough information for the intelligent system to work with. The code will be posted to the net, and comment and/or suggestions are welcome. It is eventually hoped to make this consultant system a group project with contributions from all interested members. The other program that was demonstrated was the system that Edouard Lagache has developed for is Master's Thesis research. The program is called an Educational Apprentice system and is intended to serve as an assistant to students in performing some programming assignment. Unfortunately, there wasn't sufficient time to give a reasonable explanation of the concept, so a quick review of the system's implementation details were given along with a sample run. Next months meeting will be held at Xeno Logic systems and will feature a demonstration of their accelerator card for SUN workstations. ------------------------------ Date: 1 Mar 88 05:09:25 GMT >From: ubc-vision!ubc-cs!voda@beaver.cs.washington.edu (Paul Voda) Subject: constraint satisfaction programming Trilogy is a logic programming language with constraints: In the domain of integers Trilogy solves arbitrary linear forms (Diophantine systems). For instance the query: x >= 0 & y >= 0 & 6*x + 8*y = 46 will solve without any backtracks to x = 5 y = 2 and x = 1 y = 5 Linear forms can can be combined into formulas involving ands, ors and existential quantifiers. Trilogy simplifies arbitrary such formulas. In other words, Trilogy implements the full decision procedure for the Presburger arithmetic. Trilogy contains arrays. In this domain it solves constraints of the form a(i) = v where an unknown (logical) array a is constrained in an unknown point i to the unknown value v. For instance the query a::[0..2]->[4..6] & a(0) < a(i) & a(i) < a(2) where a is a logical array of three elements with the values constrained to the interval [4..6] will solve without any backtracks to a = [4,5,6] & i = 1 See also the article 538 for the solution of the Triangle Puzzle in Trilogy. This contribution discusses a declarative technique which eliminates most of the uses of the "var" predicate of Prolog. The March issue of the Byte magazine contains a review of Trilogy. You can read there more about the language which integrates logic programming with procedural and data-base programming while remaining within the first order logic (that's why the name Trilogy: three languages within logic) Trilogy does not contain a single extralogical feature. You can also obtain from me two papers of mine on Trilogy: The Constraint Language Trilogy: Semantics and Computations and Types of Trilogy The papers discuss the logic foundations of computations and the types of Trilogy. The Byte review is admittedly, quite terse. Moreover, the reviewer criticized Trilogy for certain shortcomings when his programs were incorrectly programmed (for instance the Tower of Hanoi). But overall, the review is quite good considering the fact that the author never encountered another constraint language. ------------------------------ Date: 10 Mar 88 17:28:21 GMT >From: mcvax!enea!ttds!draken!kth!sics!alf@uunet.uu.net (Thomas Sj|land) Organization: Swedish Institute of Computer Science, Kista Subject: Destructive list predicates The ending point of Seif's message "without changing the semantics of your program" should be read "without changing the semantics of your algorithm" to make sense, I guess. I (and also Seif, implicitly) mentioned the possibility to "implement" setarg/3 using var/1 and !/0. Perhaps it should be clarified that what is meant is that you can represent a variable that you wish to modify during the execution as a partially instantiated structure (an open list containing all values assigned to the variable). This is not exactly an "implementation" since you cannot unify two "variables" represented in this way if they do not share the same instantiation history, but it is a practical programming technique, that is appropriate in many situations, if you do not wish to use setarg/3. The efficiency problem mentioned by Seif should be obvious from this. The semantic problems seem to be similar to those introduced by viewing i.e. [1.2.3|X]-X as the same d-list regardless of what X is bound to. In both cases you READ your program in a particular way, and JUSTIFY your statement about equality of "the semantics" by some more or less well-specified METHODOLOGY for implementing a given algorithm. ------------------------------ Date: 9 Mar 88 16:05:41 GMT >From: mcvax!enea!ttds!draken!kth!sics!seif@uunet.uu.net (Seif Haridi) Subject: Destructive list predicates Regarding destructive assignment in Prolog, here is our experience at SICS with this feature. SICStus Prolog (version 0.6 will be announced soon for external use) has a backtrackable assignment called setarg/3: setarg(+ArgNo,+CompoundTerm,?NewArg) which replaces destructively argument ArgNo in CompoundTerm with NewArg and the assignment is undone on backtracking. There is also a lower level nonbacktrackable assignment not available for the users. We had this feature for a while to evaluate its need. My current view is that setarg/3 is not needed as is but it has been used to implement in SICStus Prolog other features that are important for efficiency. 1. setarg/3 has been used to implement a number of predicates for manipulating logical arrays with constant access time for the latest array reference. 2. Also it has been used for implementing logical hash tables (with the possibility of removing items from the hash table). These features are needed in a project on natural language processing at SICS where a grammar dictionary is created from reading an analysing a text in natural language. The features above can of course be used on other Prolog conventional applications. 3. Another primitive that is now existing in SICStus 0.6 is an : if(+P,+Q,+R) which is: if P then Q else R this is similar to (P -> Q ; R) construct except that it allows the generation of all possible solutions for P. This construct was needed on a work going on a complete theorem prover being built at SICS for intuitionistic first order logic. This control primitive was implemented efficiently first after using the lower primitive nonbacktrackable destructive assignment. Another area where we thought first that assignment is important is the area of object oriented programming as in SmallTalk (mutable objects) specially for the important class of discrete event simulation applications. The way out was to do object oriented programming in SICStus in a way that is similar to committed choice languages (CCLs). That is to introduce a data-driven control element in the language above the normal goal driven mechanism. This is done by introducing wait declarations in the language and device a reasonably efficient suspension mechanism. This leads to a language with the added expressive power of CCLs on sequential machines but it also allows backtracking over streams. A problem arose here is how to create multiple reference to a shared object. This is done as in CCLs by creating a tree of binary merge operators to the shared object. This can be done and isolated in a single predicate called merge/2 for doing the so called multiway merge. A problem here is that sending a message to a shared object would not take a constant time. The message has to pass through a number of merge operators. This is not acceptable in all known object oriented languages. 4. The multiway merge/2 is again implemented by setarg/3 reduces the message sending delay to constant time (see Shapiro). 5. Another object in the style CCLs that is useful in is an array object that can be implemented using setarg/3. The above two features had a considerable effect on the speed of a number of discrete event simulation programs that we wrote. In summary my current point of view is that the use of setarg/3 can be isolated and hidden in a number of predicates that still can be implemented in a Prolog system ( in case of object oriented feature you need a data driven control element). The use of setarg is then to increase efficiency without changing the semantics of your program -- Seif Haridi ------------------------------ Date: 11 Mar 88 08:07:19 GMT >From: kddlab!icot32!icot!chik@uunet.uu.net (Chikayama Takashi) Subject: BSI standards I had at least one such experience. When I wrote a CROSS compiler (or rather, a cross preprocessor, that translates some language with Prolog-like syntax to another) several years ago, it was quite nasty that 0'x could not be distinguished from 120 once read in. On the target machine that uses different character codes, 120 should mean 120 but 0'x shouldn't. -- Takashi Chikayama ------------------------------ Date: 11 Mar 88 23:31:31 GMT >From: curie.dec.com!vantreeck@decwrl.dec.com Subject: BSI standards Of course user defined operators can be useful for things like prototyping. They can also end up as code that needs to be maintained by programmers that have to carefully reverse engineer the thinking behind the priorities and associativities of user defined operators to understand exactly how the program should behave. Often the maintainers may be people who don't thoroughly understand operator precedence and associativity. Careful use of a user defined operator can increase readability. But the potential for abuse is large. Languages that are being actively used by business and government are evolving into languages that strongly "encourage" programmers to write easilly maintainable code. For example, it's tough to get an Ada program to compile. But once it does compile, it tends to be more maintainable than something typically written in K&R's C or BASIC. Some complain that this trend makes it more difficult to write quick programs. But that's not the interest of people who increasingly have to bet their business or their country on correct, maintainable, software. If PROLOG is to be accepted by business and government, it had better emphasize good software engineering methodolgy (at the expense of convenience). If user defined operators are such a good idea, how come other languages are not incorporating them into their standards? You have a precedence parser for PROLOG with user defined operators that can run as fast and be as small as a one-pass recursive decent or LALR(1) parser on a PROLOG without user defined operators? Is this code public domain? I'd like to look at it. Look in the back of C, BASIC, Pascal, FORTRAN, PL/I, etc, manual. You can generally find a simple BNF and/or syntax diagram descibing the language. It doesn't require special non-standard BNFs (ones with an extra lines describing priority and associativity), nor does it require DCGs with explicit definitions of priority and associativity, nor do they require attribute grammars. Operator precedence and associativity in the above languages is implicit in the BNF or diagram. Why can't we have a simple syntax that the larger world can understand via traditional means of specifying syntax? Or is this to be standard which is fathomable only by the initiated? If there were no user defined operators allowed, then traditional means of specifying syntax would work just fine. I doubt the mountain of programmers in this world will come to Mohammud. RE: the need for strings in PROLOG. I agree PROLOG must be able to communicate with other languages. But that is what a calling standard is for. And conversion of an atom to/from a string should be isolated to the call of the foreign language. There should be no string type visible to the PROLOG programmer. There's no reason why conversions can't be handled automatically by the PROLOG compiler via glue routines. If strings are not visible to the programmer, then there's no need for it in the standard. But I suspect the real reason the BSI are putting strings in the standard is that they want to manipulate atoms like strings without having to expand them to lists, but they feel that it is too slow to assert/retract new atoms from symbol tables. This is because most implementations never garbage collect the symbol tables, they use hash tables which would have to be extended more frequently, they don't use a reference count for each string in the symbol table to know if it can be deleted, i.e., they are letting their implementation details drive the standard. Speaking from experience, I can say that it is easy to add string functions that operate on atoms and efficiently assert/retract them from the symbol tables. I resent the idea of having to add them to my PROLOG (if want to I conform to a standard) because others don't wish to garbage collect their symbol tables! My symbol table on my Mac PROLOG is an AVL tree (with a reference count). All atoms are simply pointers the strings in the tree. Often, the newly created atom becomes part of clause that is asserted. So, when backtracking happens, I simply decrement the reference count. Yes, this slower than just moving the pointer to top of heap back. But I doubt most _PROLOG_ programs spend their time doing string functions, i.e., asserting/retracting from the symbol table is infrequent. I think it's more important to have a simple, consistent language than have the fastest possible language. -- George Van Treeck ------------------------------ Date: 12 Mar 88 07:23:48 GMT >From: gast@locus.ucla.edu Subject: A Suggested Additional Predicate for Prolog Logic programming seems to me to be an ideal paradigm for dealing with combinations and permutations. If there were some way to temporarily retract a clause, but leave it's position in the database unchanged, programming permutations would be much easier and faster. In other words, the retract should be undone on backtracking. For consistency sake, an assert that is undone on backtracking should also be included, but the rest of this comment does not concern itself with a "backtrackable assert." By the way, assert and retract are unlike most predicates in that their bindings are not undone on backtracking. This behavior is non-orthogonal. Thus, I propose to have orthogonal predicates for adding to or deleting from the database. I therefore propose that the following predicate be added to Prolog. back_retract(Clause). back_retract will temporarily make that clause not part of the data- base, but back_retract will not change the clause's location in the database. When backtracking occurs, back_retract allows that clause to be unified again. It is, therefore, generally not the same as a retract and assert because back_retract does not change the position of the clause within the database. retract and assertz, on the other hand, would change the location of the clause in the database--the clause would be moved to the end of the database. While it would be difficult to write back_retract in pure Prolog, it would be easy to implement it in the implementation language if that language is not Prolog. A possible method assuming an ascii computer is to change the first character of the primary functor of the clause. For example, back_retract(x(3)) could temporarily change the name x to ^Mx, where ^M indicates that the high order bit of the next character is set. That is, the ascii representation of the predicate would be 248, not 120. As 248 does not unify with 120, pattern matching would fail. A few predicates like back_retract and assert would need to handle ^M character, but most predicates should not. This method should be fast unlike assert and retract which are frequently slow. I suggest that back_retract would be useful for many applications. (Not mutually exclusive) +) finding permutations +) solving constraints +) solving puzzles like magic squares or SEND + MORE = MONEY (see below). +) avoiding cyclic graphs (back_retract the arc). +) playing tic-tac-toe (when a move is made, back_retract that square). +) etc. In all of these cases back_retract 1) changes an N**N problem to a N! problem. 2) allows the constraints to be mixed with the part of the code generating the permutations. For example, the following program can find all of the permutations of 1, 2, and 3 (if a semi-colon causes backtracking). assert(num(1)). assert(num(2)). assert(num(3)). perm3(A,B,C) :- num(A), back_retract(num(A)), num(B), back_retract(num(B)), num(C) . In this program, num(A) instantiates A to 1. Then back_retract(num(A)) temporarily removes num(1) from the database. Then num(B) instantiates B to 2, and back_retract(num(B)), temporarily removes num(2) from the database. Finally, num(C) instantiates C to 3. The back_retract(num(C)) is not actually needed and so it is not included. Then if a semi-colon is typed, another num(C) will be tried, but there are none--num(C) is at the end of the database, so back_retract(num(B)) is backtracked, which ends the temporary retraction of num(2), and so num(2) is once again unifiable. num(B) then tries to find another instantiation--which is does by unifying B and 3. num(3) is then temporarily retracted. etc. etc. It seems as if this same technique could be used to solve crypto- arithmetic puzzles like S E N D + M O R E --------- M O N E Y (Colmerauer, CACM, Dec 85, page 1310). --------program follows-------- Since M must be 1, we call puz, so that M is instantiated to 1. Colmerauer checks to see that M and S are not equal to zero. My constraint is equivalent. */ % Assert the possible numbers for the other letters. 1 is not included % since M=1. :- assert(num(0)). :- assert(num(2)). :- assert(num(3)). :- assert(num(4)). :- assert(num(5)). :- assert(num(6)). :- assert(num(7)). :- assert(num(8)). :- assert(num(9)). % call with M = 1 to get one solution. If the argument is a variable, % then backtracking can occur, but no other solutions are found. % solve from right to left puz(M) :- M=1, num(D), back_retract(D), num(E), back_retract(E), constraint(C1,Y,D,E,0), num(Y), back_retract(Y), num(N), back_retract(N), num(R), back_retract(R), constraint(C2,E,N,R,C1), % already back_retracted E. num(E), % already back_retracted E. num(O), back_retract(D), constraint(C3,N,E,O,C2), % already back_retracted N. num(S), back_retract(D), constraint(C4,O,S,M,C3), % already back_retracted O. % Really, all we have to check is that M=C4=1, % but we do it the long way constraint(0,M,0,0,C4), % output the answer tab(2), write(S), write(E), write(N), write(D), nl, write(' +'), write(M), write(O), write(R), write(E), nl, tab(1),write(M), write(O), write(N), write(E), write(Y), nl. % constraint(-carryout, -sum, +add1, +add2, +carryin) % First get case where no carry out. Then case where there is carry out. constraint(0, Sum, Add1, Add2, CarryIn) :- Sum is Add1 + Add2 + CarryIn, Sum =< 9, !. constraint(1, Sum, Add1, Add2, CarryIn) :- Sum is Add1 + Add2 + CarryIn - 10. --------program ends-------- The use of the back_retract allows the combinatoric aspect of the program to be nicely interleaved with the constraint side of the program. This program can be implemented in Prolog without using back_retract, but it is slower and the user is forced to do significantly more typing which is error prone. Alternatively, "member" and "lists" could be used, but their use is not all that convenient either. For example, using the same basic structure as above, we can write: puz(M) :- M=1, num(D), num(E), E \= D, constraint(C1,Y,D,E,0), num(Y), Y \=D, Y \= E, num(N), N \= D, N \= E, N \= Y, num(R), R \= D, R \= E, R \= Y, R \= N, constraint(C2,E,N,R,C1), % already know \= M, D, Y, N, R num(E), num(O), O \= D, O \= E, O \= Y, O \= N, O \= R, constraint(C3,N,E,O,C2), % already know \= M, D, E, Y, R, O num(S), S \= D, S \= E, S \= Y, S \= N, S \= R, S \= O, constraint(C4,O,S,M,C3), % already know \= M, D, E, Y, N, R, O, S % Really, all we have to check is that M=C4=1, % but we do it the long way constraint(0,M,0,0,C4), tab(2), write(S), write(E), write(N), write(D), nl, write(' +'), write(M), write(O), write(R), write(E), nl, tab(1),write(M), write(O), write(N), write(E), write(Y), nl. The other predicates are unchanged and so are not shown again. This program in C-prolog takes in 3.2 seconds of user time on a Sun 3. (By examining the constraints closely, I sure it could be made faster). Thus, back_retract(S), in the program serves the same purpose as S \= D, S \= E, S \= Y, S \= N, S \= R, S \= O, in the alternative. Thus, because it is orthogonal with most of the rest of Prolog and it is useful, I recommend back_retract be included in Prolog. I look forward to hearing your comments -- David Gast ------------------------------ Date: 13 Mar 88 22:33:52 GMT >From: antares!finin@burdvax.prc.unisys.com (Tim Finin) Subject: A Suggested Additional Predicate for Prolog I recall that Micro-Planner had such predicates for assert and retract. I think that the normal assert (THASSERT) and retract predicates (THREMOVE?) predicates had the desired behavior and that there were alternates which were not undone on backup. -- Tim ------------------------------ Date: 14 Mar 88 05:02:58 GMT >From: quintus!ok@unix.sri.com (Richard A. O'Keefe) Subject: A Suggested Additional Predicate for Prolog Eh? Remember, N! gets *very* big, *very* fast. What does it matter how fast "programming permutations" is, when doing it at all is the kiss of death to efficiency? I hope I've misunderstood. Eh? The variable _bindings_ most certainly ARE undone! The change to the data base is not, but then write/1 doesn't erase the screen and read/1 doesn't reach out and shove your fingers backwards either. You forgot the smiley. The only Prolog interpreter I've ever seen where the text of the clause was stored was one done by Michael McCord in SNOBOL. There are ways that an enabled/disabled flag could be cheaply associated with a clause, but I strongly suspect that Mr Gast hasn't thought through the interactions between back_retract/1 and the cut. What is supposed to happen if I do back_retract(foo), abort. Is foo supposed to be gone, or not? Stirling's approximation: N! = sqrt(2*pi*N) * (N/e)**N * (1 + 1/12N + 1/288N**2 + O(1/N**3)) For example, (N!)/(N**N) ~=~ 9x10**-9 for N=21, which looks like a big improvement, but 21! ~=~ 5x10**19. Suppose an operation takes 1 microsecond, for what value of N would doing it N! times take more than a year? There are roughly 3.16x10**7 seconds in a year, so for what value of N is N! > 3.16x10**13? 16! is 1.5 times too small, 17! is 11 times too big. Think about it: if the basic operation costs 1 microsecond, and we do N! of them, for N=17 it will take 11 years. For N=14, it will take a little over a day. Converting an N**N algorithm to an N! one converts something which is practically impossible to something which is only practically impossible. ------------------------------ Date: 14 Mar 88 07:40:24 GMT >From: quintus!ok@unix.sri.com (Richard A. O'Keefe) Subject: Re: BSI Proposal Well, yes and no. The grimoire doesn't explain what the Constraint line means, and I had to guess. The "February 88" draft has three rules (5.4, 5.4 (sic), and 5.5) for parentheses, and the "Feb 88" one has only one (5.5). If I had taken rule 5.5 in the "Feb 88" draft seriously, I would have been forced to the conclusion that (0) was not a legal term in BSI Prolog! I jumped to the conclusion that rule 5.5 should have had 'h' as its left-hand constraint because fairly serious nonsense would result if 5.5 wasn't fixed somehow. Well, it depends what you mean by a symbol. I regard "fred(" or ":-(" as a single token. It seems just as reasonable to do that as to regard "1.0e-4" as a single token, or do you want to allow spaces there too? I know, I've had that kind of trouble with typists too. I had a perfectly straightforward piece of ordinary mathematical text which I had to send back three times once, and finally had to type it myself. Putting a space after a left parenthesis or before a right parenthesis is appallingly bad English punctuation, so it sounds as though you must have a lot of trouble with your typists working on English too. None of the mathematical or logical texts on my bookshelves puts a space between a function symbol or predicate symbol and its left parenthesis, EXCEPT when the function or predicate symbol is UNARY. When you are using "Curried" functions, they are of course unary, so if you have defined f = lambda x. lambda y. lambda z. h(x,g(y),z) it is entirely appropriate to write f 1 and f 2 3 but if you have defined f = lambda(x,y,z). h(x,g(y),z) it is good style to write f(1,2,3) rather than f (1,2,3) Many logicians and mathematicians habitually use Greek letters, subscripts and superscripts, and do exotic things like using (( as an infix relational operator. Do you regard the fact that a typist is likely to mistake an iota for an i or an epsilon for an e as an argument that mathematiciains should not use Greek letters? Should we outlaw vertical bars because bad typists think they are solidii or ells or capital Is? And while we're at it, a lot of people like using hyphens and don't understand or don't like the break character, so shouldn't we throw out "_" and allow instead identifiers like this-is-one-token. After all, typists often mistake "_" for "-". As Chris Moss says, most languages since Fortran regard blanks as significant. Surely it is inconsistent to argue that "RED O" and "REDO" are different, and that is a Good Thing, but "red (O)" and "red(O)" being different is a Bad Thing? Blanks are being treated as significant in both cases. "RED O" and "red (" are both two tokens, and "REDO" and "red(" are both one token; it's exactly the same thing. What's sauce for the goose is sauce for the gander. As it happens, I'm an Algol 68 fan. I like having spaces inside identifiers, rather than underscores or hyphens. I even have a version of the public-domain parser which lets me treat list length([], 0). list length([_|Tail], succ(N)) :- list length(Tail, N). as Prolog. ("list length" turns into "list_length".) Does this mean I think the standard should allow spaces inside identifiers? No way! I think this is 10% better than what we have now, which is good enough to put it in some other language, but it's nowhere _near_ enough of an improvement to change the language we already have. By lexical rule L29, ":" and "-" are graphic characters. By lexical rule L7, ":-" is a graphic symbol. By lexical rule L3, ":-" is thus an atom. By syntax rule 5.4, <atom> "(" <termlist> ")" is a term/h. The only constraint is that if <atom> is a prefix operator, there must be no space between <atom> and "(". Therefore :-(p,q) ***IS*** in the grammar. No, the grimoire says very very clearly that both (a,b) and (a&b) are mapped to the same Abstract, namely sys(and, [func(a,[]), func(b,[])]) ***LEXICAL*** rule L19 says and symbol = "&" | "," ; so when we get to syntax rule 4.1 goals = term, [and symbol, goals] ; Constraint X X X Abstract sys(and,[A,B]) A B there is no possibility of distinguishing between "," and "&": there is *NOTHING* associated with the "and symbol" which can participate in the Abstract. "&" is not equivalent to "," between <function(> and <)> or between <[> and <]>. But functioning as an "and symbol" it is quite indistiguishable from ",", at least according to the grimoire, and that is all I can go on. Quite right. In fact, since the grimoire says on page 5 "The following table defines the "is_op" table used in clauses 8-10 above", it would be closer to the truth to say that the grimoire forbids user-defined operators entirely. Silly me. But the question of which symbols the programmer can declare as operators is surely a syntactic question. If I want to know what operators I can declare in Algol 68, I look in the grammar. If I want to know what operators I can overload in ADA, I look in the grammar. If I want to know what operators I can declare in Pop-2, I look in the grammar, which tells me that operators look just like other symbols. If not in the grimoire, where SHOULD I look to find out what operators I can declare? I agree that it is a mistake, from the point of view of language design. I keep asking people here at Quintus not to use it, and when I edit any system files I surreptitiously change "|"s to ";"s. But Quintus don't claim to have a SUPERIOR syntax, they claim to have a COMPATIBLE syntax, and compatible means compatible, even with features I might not happen to like. I think this line has been misread: I meant the comment to indicate that (a) I don't like it, but (b) because it is part of the de facto standard it *should* be retained in BSI Prolog. Everyone will go for (3), of course. But that is something of a red herring, as BSI Prolog won't allow it. Sure I'd like to be able to write every group is a monoid. Oh, "natural language symbols" didn't mean that? Silly me. I'd like a language in which I could use branching quantifiers and modal operators. Oh, "logical symbols" didn't mean that? Silly me. The interpretation I *want* is the one [a] gets. What I *fear* is that ('->'(p,q) ; r) will get the *other* one. [b] would be illegal for the simple reason that the grimoire does not list "->" and ";" at the foot of page 5 (the table of built in operators) and provides no other means of making ANY atoms legal operators. However, By lexical rule L29, "-" and ">" are graphic characters. By lexical rule L6, "->" is a graphic symbol. By lexical rule L3, "->" is an atom. By lexical rules L4 and L3, "p" and "q" are atoms. By syntax rule 5.3, p and q are terms, and by syntax rule 6, "p, q" is a termlist. By syntax rule 5.4, "->(p, q)" is therefore a legal term. Indeed, since "->" is not a prefix operator, "-> (p, q)" is also a legal term. So [c] is ***NOT*** illegal. Even if operators had to be quoted, by virtue of the fact that the control structures are hardwired into the grammar, '->' and ';' do not appear in is_op/3, the table of built-in operators, it follows from syntax rules 8, 9, and 10 that -> is neither a prefix op, nor a postfix op, nor an infix op. Even if it were an infix op, that would not make ->(p,q) illegal, at least not in the version of the grimoire that I was citing (the "Feb 88" one, not the "February 88" one). Not true. I referred (as quoted!) to syntax rule 0, which is explicitly described as "the interface between the two sections". If this does not "explicitly make any correspondence between tokens and programs", what DOES it do? About your intentions, I have nothing to say. You are the only authority. About your *actions*, I can only say that whatever you intend, BSI Prolog is about as different from Edinburgh Prolog as Turbo Pascal is from ISO Pascal. When I saw that the BSI committee had had the effrontery to propose their stuff to ISO, I was speechless with rage. I think the ISO approach to internetworking is enough to show that being accepted by some number of ISO countries is no guarantee of quality. This applies to the rules proper only. It does not apply to the lines labelled "Constraint", "Abstract", "Priority", "Input", "Output". There are at least two problems with these additional lines. The first, of course, is that they use a two-dimensional format where the number of spaces is vitally significant: foo = baz, ugh ; Thingy X X and foo = baz, ugh ; Thingy X X are *very* different. If allowing arbitrary amounts of space inside a <function(> token is such a wonderful thing, the grimoire should take its own medicine. Perhaps something like foo = baz, ugh ; Thingy X : X, _ ; and foo = baz, ugh ; Thingy X : _, X ; One also has to watch out for the fact that some lines are omitted from some rules. I believe it to be the case that to determine which attributes are relevant to what non-terminals it is necessary to examine the entire grammar. But the second, and biggest problem, is that not only are these new lines not part of BS6154, the whole thing is a new formalism which is not described in any of the documents that the BSI committee have sent me. What does it mean when a rule of the grimoire says Rule foo = baz, [ ugh ] ; Abstract f(X,Y) X Y I *think* it means foo = baz, ugh ; f(X,Y) X Y + foo = baz ; f(X,[]) but I can find nothing that says so. What does it mean when a rule of the grimoire uses Rule .... { stuff } .... Abstract X Other k I *think* it means Rule .... stuff-star .... Abstract X Other k where Rule stuff-star = empty ; Abstract [] Other K + Rule stuff-star = stuff, stuff-star ; Abstract [X|Xs] X Xs Other K K K but I can find nothing that says so, neither is it said anywhere which attributes participate in listification and which do not. Now the one thing a standard _must_ not do is leave you guessing! > Lots of people have wanted their own pet ideas in the standard ... I don't want *ANY* of *my* pet ideas in the standard. Look, if you took Fernando's version of C Prolog (not mine) and stamped "BSI" on it, I wouldn't mind much. Dash it, you could take *ALS* Prolog and stamp "BSI" on it, and I'd think more highly of the BSI committee. All I want is a standard which is close to existing practice and spells things out in rather more detail than most manuals. I want everyone reading this to understand my position clearly: (1) what would be a good syntax for a logic programming language? (2) what should the standard syntax be? I regard these as two very different questions. I think Pascal syntax is little short of insane, but that doesn't mean that I think the Pascal _standard_ should have departed from it. I think C syntax is bizarre, but that doesn't mean that I think X3J11 should redesign it. When I write down logical clauses, I use '<-" for if, '&' for and, '|' for or, and am as likely to use ';' at the end as '.'. So what? That's not the way Edinburgh Prolog ***IS***. A committee such as the BSI Prolog one is not the best way to answer question (1). The right thing to do is to perform experiments. Richard (there is little so bad that changing it won't make it worse) O'Keefe ------------------------------ End of PROLOG Digest ********************