The "empty atom" ... is it legitimate?



?- atom("").

Why have an “empty atom”? Should an atom not be always nonempty?

On second thoughts, there seems to be a bijective mapping between atoms and strings and lists of characters, so having it makes sense.

On the other hand, I tried to use the empty atom as the empty functor, but that doesn’t work:

?- X = ""(1,2).
ERROR: Syntax error: Operator expected
ERROR: X = "
ERROR: ** here **
ERROR: "(1,2) . 

Note that the empty atom is '', not ””, whose interpretation depends on the double_quotes flag.

Yes, it works:

?- X = ''(1, 2).
X = ''(1, 2).

?- Empty_atom = "", X =.. [Empty_atom, 1, 2].
Empty_atom = '',
X = ''(1, 2).

Another experiment:

?- X =.. ["", 1, 2].
ERROR: Type error: `atom' expected, found `""' (a string)
ERROR:   [10] _7044=..["",1|...]
ERROR:    [9] <user>
?- set_prolog_flag(double_quotes, atom).

?- X =.. ["", 1, 2].
X = ''(1, 2).

I am not in the mood for reading code at the moment, but my guess is that this is an oversight in regards to the treatment of double quotes during parsing.

PS: it seems that the name of the functor doesn’t need to be an atom, strictly – it can also be “atomic”.

?- atom([]).

?- X = [](a, b).
X = [](a, b).

?- X = [](1, 2), X =.. [A,B,C].
X = [](1, 2),
A = [],
B = 1,
C = 2.

?- X = [](1, 2), X =.. [A,B,C], atom(A).

I don’t know what to do with this knowledge :slight_smile:

1 Like

It is frustrating that the mysteries of Prolog implementations are not as fundamental or of general appeal as the mysteries of High Energy Physics.

1 Like

Just to make sure, it still seems there is a small inconsistency. I don’t want to throw the “bug” word around without need, but still, the error message that you see is a bit fishy.

To summarize:

  • yes, empty atoms (strings, lists…) are fine;
  • Yes, you can use the empty atom as a name to a compound term;
  • Yes, you can set double_quotes to atom and then use =.. to make a compound term with an empty atom for a name;
  • No, you cannot just type ""(1, 2). Given everything else, this should also work, but apparently it doesn’t.
1 Like

Because Prolog’s grammar doesn’t allow ""(1,2) (or "abc"(1,2) for that matter). The grammar does allow double quotes in other contexts, such as X="abc"; the interpretation varies according to the double_quotes flag.


Good to know. I am still struggling to understand the need for "atoms in double quotes" (like, why?)

The settings for double_quotes and back_quotes give you full flexibility of representations. (Single quotes always get you atoms, and that’s baked into the grammar, which is why 'atom with spaces'(1,2) is just fine.)

Originally “…” meant a list of codes (that is: "abc" = [97, 98, 99]"). For convenience, SWI-Prolog has taken over the “…” notation for strings.
See also: SWI-Prolog -- Manual and SWI-Prolog -- Manual

1 Like

Possibly. I kind of sympathize with the idea of @Boris and am tempted to call this a bug. On the other hand this seems totally artificial and not worth “fixing”.

Allowing "abc"(1,2) in the syntax would mean that a program could fail to compile based on a directive. There’s nothing inherently wrong with that – e.g., Python2 has from __future__ import print_function which determines whether print "abc" is legal or not (with the directive, only print("abc") is legal). [In the case of Python, this is easy to do – simply remove print from the lexical analyzer’s list of keywords.]

1 Like

In furtherance of this, I have noticed:

% A term with the empty atom as functor

?- ?- F=..['','a','b','c','d'], write_canonical(F).
F = ''(a, b, c, d).
% A term with the atom '[]' as functor

?- F=..['[]','a','b','c','d'], write_canonical(F).
F = '[]'(a, b, c, d).

But now:

% A term with the empty list as functor
?- F=..[[],'a','b','c','d'], F=..[H,A1,A2,A3,A4], 
    write_canonical(F), atomic(H), \+atom(H).
F = [](a, b, c, d),
H = [],
A1 = a,
A2 = b,
A3 = c,
A4 = d.

That’s probably a leftover from when the empty list used to be an atom.


16 ?- writeq([](a,b)).

17 ?- writeq('[]'(a,b)).

18 ?- [](a,b) == '[]'(a,b).

[] is a blob and these are allowed as functor name. They started of as an abstraction of atoms, turning normal atoms into a subtype. Whether you want to do this is another issue. Not sure there is anything meaningful about this code:

19 ?- open_null_stream(X), T =.. [X,a].
X = <stream>(0x55d87c5af790),
T = <stream>(0x55d87c5af790)(a).

Using [] as a functor name is not that uncommon though and there was no reason to make this illegal.


However, it says that [] is not blob type.

?- is_of_type(blob, []).
?- is_of_type(T, []).
ERROR: Arguments are not sufficiently instantiated
ERROR:   [12] throw(error(instantiation_error,_3294))
ERROR:    [9] toplevel_call(user:user: ...) at 

Also it says that [] is not an atom. I thought a functor name must be an atom. Since [] is not an atom

?- atom([]).

that example surprises me a little bit.

?- functor(X, [], 2).
X = [](_6178, _6180).

I hope no new prologers are confused by this, like an old prologer like me.

is_of_type/2 does not define the blob type.

?- blob([], X).
X = reserved_symbol.

Blobs can be used as functor names. This is there for some years and it doesn’t seem to cause many problems. The biggest problem caused by blobs is that terms written with blobs in them can (often) not be read. This is for most blobs on purpose though as it allows us to safely garbage collect the data behind the blob. That doesn’t hold for the reserved symbol blobs of course. These are permanent.

Thanks for reply for so delayed response. It takes time for me to accustom to the thought that [] is not an atom, but is a empty blob and a empty list. It is difficult to imagine that such thought causes practical serious confusion, but conceptually I feel some gap between the empty blob [] and list and blob in general, though I am not interested in such issue on semantical interpretation. For the time being, I talk to myself that the empty blob is like an urelement in the set theory.