[comp.lang.prolog] PROLOG DIGEST V6 #24

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
********************