[mercury-users] Re: Lisp-like syntax for Mercury (Mercury & macros)

Richard A. O'Keefe ok at cs.otago.ac.nz
Mon Jun 10 11:18:40 AEST 2002


	How about font-locking with things like heavy overloading of the quote
	character (0'a, 'term'(...), 'string')?

I don't want, don't use, and therefore in my editor, don't have
font-lock.  So no problem.  However, term movement gets 0'a and 'xxx'
perfectly correct, not hard at all.  I note that of your three examples,
there are really only TWO cases:  <decimal integer>'<based integer>
and '<quoted symbol>'.  Ever since based integers were introduced in
DEC-10 Prolog, character sequences like 8'7'x... have been locally
ambiguous (is this 8'7 followed by 'x...  or is it 8 followed by '7'
followed by x...) so the rule has been never to put a quoted operator
directly after a number without intervening white space.

I will admit that I personally would NEVER have chosen the apostrophe
here, but would have chosen the Algol 68 'r'.  Unfortuntaely, the
DEC-10 Prolog designers were influenced to some degree by POP-2, where
the radix character was ':', so they looked for a punctuation mark.

	How about automatic indentation
	(e.g. 3.14 versus `.' as the end of clause)?

I have never found an Emacs mode where automatic indentation was even
tolerable.  Having had so many horrible experiences with Emacs auto-
indentation, especially in C, the only automatic indentation I put
up with is LF "new line at same indentation level" vs CR "new line at
zero indentation level".  However, '.' followed by white space is
end of clause, '.' followed by anything else isn't.  For indentation-as-
you-type, the answer is even simpler: have a command that means
"end of clause".

I note that an end-of-clause command is quite useful.
When I was able to use the TOP editor on TOPS-10 (thanks, Pop people,
and thanks, Dave Bowen) I had it set so that with no command modifiers,
<end of clause command> copied the predicate name and arity from the
clause being ended, so that
    foo(X, Y, Z) :-
        bar(Y, Z, X)<end of clause>
gave you
    foo(X, Y, Z) :-
        bar(Y, Z, X)
    foo(<here>, , ) :-


	What if I better read terms with the parentheses separated from
	the functor, e.g. `term (Foo)' instead of `term(Foo)'?

I cannot parse your English here.  'term (Foo)' is a syntax error unless
'term' is declared as an operator.  So you have to tell your parser what
the operators are.

	All that is solvable in Emacs, but no way *EASY*.
	
Yes, but that's at least as much Emacs' fault as Prolog's.
All of the things you have mentioned are quite easy to do IF you
use a proper parser for the language you are editing.  (With a few
wrinkles.  It has to be prepared to stop in mid-flight, for example.)
If you try to do it on the cheap, you are going to run into problems.

	    RAO> 	(defmodule sort
	    RAO> 	  (:export main))
		
	    RAO> What happened to the arity?
	
	It's intentionally omitted as well as the type specification.  I think
	it's not a good idea to export only a certain part of the predicate
	definitions put under the same name.

You are free to make that choice, but you are NOT free to call the result
an alternative syntax for Mercury.  It is a lisp-ish syntax for a related
but semantically different language.

We've HAD atom-based modules for Prolog, notably MPROLOG.
The Quintus module system owes a lot to earlier work by Dave Bowen
when he was at Edinburgh; the Edinburgh reaction to MPROLOG was
dismay at something so obviously wrong.  It's like saying "let's have
a way to export everything beginning with the letter A."

	I also don't like defining
	predicates with the same name and different arity too much, but that
	might be just a complex introduced by my Java programming.
	
But Java lets you do this.  In fact, the Java libraries do it a lot.
Do not let your (justified) disgust at Java as a whole affect perfectly
innocent techniques in other languages.


	    RAO> 	(define main (* *)
	    RAO> 	  (:types (io:state io:state)
	    RAO> 	   :modes ((di uo :det)))
	
	    RAO> This strikes me as rather un-lispy.  Why not
	
	    RAO> 	(define (main (W0 io:state) (W io:state))
	
	This is what I tried at the first attempt, but I've found it a bit
	unreadable.  The problem is that you must specify types for all the
	arguments in Mercury, and there are often many arguments in logic
	programming.

So?  What's the problem?  Programmers in other languages have faced and
solved this problem long ago.  If you have too many arguments to fit on
one line, you switch to an alternative layout that puts one argument
per line.

    (define (foo
              (t1)      ; comment
              (t2)      ; comment
              (t3))     ; comment

	This is unlike defmethod, where you usually qualify only
	one or two arguments.

Hmm, when I use defmethod, I usually only HAVE one or two arguments.

	Consider additionally the multiple modes and you
	can see the most natural way is probably not the best way.
	
Can we agree that there ought to be a fused syntax for the common case
where there is a single mode?

    (define (foo
              (:in t1)    ; comment
              (:in t2)    ; comment
              (:out t3)   ; comment
              :det)


	    RAO> Here I part company with you.  The use of square brackets is common
	    RAO> in some Scheme dialects, and was known in Interlisp (where brackets
	    RAO> were "stronger" than parentheses, so [(((x] was legal).  But it is
	    RAO> not part of normal (Common) Lisp practice, nor blessed by any version
	    RAO> of the Scheme report.
	
	Prolog and Mercury clearly separate terms and lists and I like it.
	Would you like to suggest a better term notation than the square
	brackets?
	
If you want a Lispy syntax that clearly separates terms and lists,
make terms follow the normal Lisp convention for functions, and make
*lists* the things that are different.  E.g.,

    (define (append (Xs (list T)) (Ys (list T)) (Zs (list T))
              :mode (in in out det)
              :mode (out out in non-det))
      (case [Xs Zs]
        ([[] []]              (true))
        ([[A . As] [A . Cs]]  (append As Ys Cs))))

The average Lisp programmer writes more function calls than data lists.

	    RAO> I can't help thinking that using 'and' would be lispier than
	    RAO> using /.
	
	It would be lispier, but AND is so common in logic programming that
	using it explicitly makes the sources unreadable.

Well, no.  You can elide the 'and' in many cases, just as you can elide
the 'progn' in many cases in Lisp.  In particular, the top level of a
predicate definition, or a clause of a COND or CASE form.  You only need
explicit 'and' inside 'or'.

	I no way insist on
	using `/' -- it's just a randomly selected character that can be typed
	without pressing Shift, doesn't conflict with common Lisp syntax (which
	doesn't apply to `;' unfortunately) and makes a good visual separation.
	
	And I've also thought Ralph Becket would be glad to see a bit of infix
	notation in the syntax ;-).
	
It is just too confusing to try to combine Lispy syntax and infix syntax.
(Take it from me; I've used Interlisp and I know these things (:-))

	There have to be a distinction between DCG "invisible" variables and
	anonymous variables.

Of course there does, because the hidden variables are not anonymous.
(Although I repeat that enough Prolog dialects have used "*" for an
anonymous variable that I find these stars confusing.)  Using
W0, W1, W2, ... W notation for "World state" arguments is a mild pain,
but not a big pain.  If it pushes people to write as much of their code
without such arguments as they can, that might be no bad thing.

	I like the idea using :io instead of `* *'.  (OTOH
	I don't like the idea to expand the DCG variables by hand as shown
	below, it's very bothering.)
	
Doesn't bother _me_.  Which I suppose is the point.
You can't satisfy everyone.

	I agree, but practical matters play role here.  I don't like the Paul
	Graham's notation of Prolog variables (`?var') for two reasons: It
	requires pressing Shift and it makes each variable name one character
	longer, thus requiring much more line breaks in logic programming.  The
	comma syntax fixes only the first problem.
	
The comma syntax is not arbitrary; it's Lisp (more precisely, Scheme, in
my mind) backquote syntax without the backquote.

The "?" notation is hardly Paul Graham's; IIRC it goes back at least as
far as PLANNER and CONNIVER.  At any rate, it has been "conventional"
Lisp notation for pattern variables for a long time.

One final suggestion.  Others have embedded Prolog dialects in Lisp.
The most notable was Alan Robinson's LogLisp.
Dorai Sitaram's ScheLog has been quite popular:
http://www.ccs.neu.edu/home/dorai/schelog/schelog.html
Norvig's Prolog-In-Common-Lisp (compiles Prolog to Lisp) in his
well-known book is also fairly popular.
Then of course there's the old micro-PROLOG which used a paren-heavy
syntax of its own.

It might be well to look for ideas among those.
--------------------------------------------------------------------------
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the users mailing list