Subject: Idea: [] != '[]'?

From: Jan Wielemaker <[email-masked]>
Date: Tue, 16 May 2000 12:07:14 +0200

Hi,

Sometime ago Paul Singleton talked about using nested lists for various
purposes.  He pointed at the ambiguity that [] is both an atom and the
empty list.  I've come across this various times, as I also sometimes
come acress foo == foo().  I.e. with a representation where I have
atoms (for example representing text) and actions represented as
structures and I want:

	doit(Text) :-
		atom(Text), !,
		...
	doit(foo()) :-
		...

But as foo() is illegal syntax, this doesn't work.

* [] != '[]
===========

Both can be cured, extending SWI-Prolog.  First let us consider the
empty list.  This is an odd atom (and it is odd that the empty list,
which is a list after all is also an atom).  All these thing yield
exactly the same thing: an atom with the two characters [ and ].

	[], [ ], [/*hello*], '[]'

An alternative would be to turn [] into an atom that has some odd
properties:

	* It is returned by reading [], [ ], [/*hello*/]
	* It is written as [] (note that without precautions in
	  write/1 it is written as '[]').
	* It does *not* unify with '[]'

We can even go further:

	* atom/1 fails on it.  Just is_list/1 succeeds.
	* atom_chars/codes, etc. raise an exception on it:
	  it has no character representation.

Of course, '[]' behaves as an atom holding these two characters
and printed as '[]'.

Compatibility issues:

	* Code explicitly using '[]' as an empty-list will fail.
	  Does such code exist?

	* Foreign code doing PL_new_atom("[]") to get access to
	  the empty list will fail.  The interface already defines
	  PL_put_nil(), PL_unify_nil(), etc.  This appears
	  acceptable.

Implementation:

	* Most likely simple.  We just create the atom [] using
	  special code such that no such atom can be created from
	  a string.  Read and write already have special code.

Votes?

* Introducing foo()

I.e. compounds without arguments.  Basically this just means making
read/1 not check for it: internally these things already exist.  More
difficult is the integration with atoms.  What about the following:

	* X =.. [foo] ---> X = foo()
	
	* Does calling foo() fire the clause foo :- bar?  Or just
	  foo() :- bar?  In the first case writing foo :- bar is
	  no more then a shorthand for writing foo() :- bar, which
	  is actually the case if you look at the current compiler.

	  Same holds for calling an atom.

	* It is easy to add a compatibility flag (which is not the
	  case for the []/'[]' thing).

Votes?

	Regards --- Jan