Using `[]` as predicate name

It’s allowed to use [] as a predicate head which is quite useful for implementations for [] as a postfix operator (e.g., array notation). However library(prolog_code) exports predicate predicate_label/2 which trips over these predicates, e.g.,

?- predicate_label([]/3,L).
ERROR: Type error: `text' expected, found `[]' (an empty_list)
ERROR: In:
ERROR:   [13] atomic_list_concat([[],/|...],_41854)
ERROR:   [12] prolog_code:predicate_label(([])/3,_41898) at swipl/library/prolog_code.pl:284

Clearly this can be fixed in library(prolog_code) but perhaps a better option is to extend the semantics of atomic_list_concat/2 to allow [] in the input list (it is atomic although not an atom).

Any opinions?

Not sure. The entire purpose of changing [] was to make it not an atom. I’d be more inclined to patch predicate_label/2.

Note that the name of the primitive is atomic_list_concat not atom_list_concat. So I’m not saying that [] should be an atom (that would be a NUC), but that atomic_list_concat should accept it as atomic.

Same argument applies to atomic_concat and atomics_to_string, i.e., they should accept anything that passes the atomic/1 test.

I don’t think so. These predicates are about “text” atomics. They should definitely not apply to stream blobs, clause reference blobs, etc. All these also pass atomic/1. [] was deliberately placed in the non-text atom(ics).

It is a compatibility hack to allow [] as a predicate name, something that is otherwise restricted to text atoms.

So what exactly are “text” atomics? atomic/1 certainly doesn’t define them although it does talk about [] and “blobs”.

And, to be honest, I don’t see why [] couldn’t be a “text” atomic. It certainly has a well-defined text representation. And while somewhat more dubious (and less useful), the same applies to blobs - just print one.

?- clause(lists:member(_,_),_,Blob),format(atom(A),"~w",[Blob]).
Blob = <clause>(0x7fe1f7604d40),
A = '<clause>(0x7fe1f7604d40)'.

So I don’t really get the rationale behind “text” atomics as a subset of atomics.

Well the predicate name '[]' could have been used instead, then no compatibility hack required (compatibility with what?).

Similarly, I don’t get the rationale for “text atoms”, whatever they are. Since all atoms seem to be “text atomics” aren’t they, by definition, “text”? Or are there two definitions of “text” in play here?

Treating [] as an atom seems likely to cause confusion:

?- write([]), nl, write('[]'), nl.
[]
[]
true.

?- writeq([]), nl, writeq('[]'), nl.
[]
'[]'
true.
1 Like

One of the good points about [] not being text is that the various representations become unambiguous (atom, string, list of char/code). With [] being text, it is unclear whether it represents "" or "[]".

And indeed the docs do not talk explicitly about “text atoms”, but implicitly atom/1 tests for text atoms. The blobs are technically the same as atoms internally, atomic/1 succeeds and atom/1 fails. The distinction is more explicit in the foreign API. See SWI-Prolog -- Defining a BLOB type

1 Like

It’s hard for me to follow this argument without a definition of “text”. But a floating point number, for example, has a number of possible text representations (e.g., “10.0” or “1.0e1”) - you need to pick one depending on context, or provide a wealth of options as in the suite of output predicates. In the case of the atomic_list_concat/2 predicate, the context has determined that 10.0 is represented '10.0' (not '1.0e1') and I don’t see why [] shouldn’t be represented as '[]' (not ''). Other contexts may make a different choice.

I don’t think this is worth a long discussion. It’s not unreasonable to patch prolog_code to adhere to the “compatibility hack” introduced by allowing [] as a predicate name, even though it’s not an atom.

But let me make the following point: at the language level, there is no term type of “text” in Prolog. Indeed every term has a text representation, and often more than one. There is a term type atomic and I think it’s a little perverse that builtin predicates whose names are prefixed by atomic don’t actually support everything that is defined to beatomic.

I also think it’s a bit unfortunate that terms which are written with the [] operator result in compound terms whose name is not an atom. But I guess there were some awkward choices to be made that feature was introduced.

BTW, you may have similar issues with the pce version when profiling a goal which calls the [] predicate. Running on v9.2.9:

ERROR: [Thread pce] Unhandled exception: Type error: `text' expected, found `[]' (an empty_list)
ERROR: [Thread pce] In:
ERROR: [Thread pce]   [19] atomic_list_concat([type_ndarray,:|...],_7018)
ERROR: [Thread pce]   [16] Send-method on @17575124019903/prof_dict_item: prof_dict_item->initialise(node{call:210000,callees: ...,callers: ...,exit:180000,predicate: ...,redo:0,ticks_self:36,ticks_siblings:372},ticks,@17575124016481/prof_frame) at swipl/xpce/prolog/lib/swi/pce_profile.pl:302

With a patched version of prolog_code it manages to display the top level profile data window without error, but if I select a predicate which calls [] I get:

ERROR: [Thread pce] prolog_predicate <-name: Argument 1 (name): `name' expected, found `[]'
ERROR: [Thread pce] prof_node_text ->initialise: Argument 1 (any): `any' expected, found `prolog_predicate(type_ndarray:([])/3)'
ERROR: [Thread pce] tabular ->append: Argument 1 (label): `name|graphical|table_cell' expected, found `prof_predicate_text(type_ndarray:([])/3,child)'
^C
Action (h for help) ? abort
% Execution Aborted

And if I acually select the [] predicate, it goes into an infinite loop:

ERROR: [Thread pce] prolog_predicate <-name: Argument 1 (name): `name' expected, found `[]'
ERROR: [Thread pce] prof_node_text ->initialise: Argument 1 (any): `any' expected, found `prolog_predicate(type_ndarray:([])/3)'
ERROR: [Thread pce] prolog_predicate <-name: Argument 1 (name): `name' expected, found `[]'
ERROR: [Thread pce] prof_node_text ->initialise: Argument 1 (any): `any' expected, found `prolog_predicate(type_ndarray:([])/3)'
ERROR: [Thread pce] prolog_predicate <-name: Argument 1 (name): `name' expected, found `[]'
ERROR: [Thread pce] prof_node_text ->initialise: Argument 1 (any): `any' expected, found `prolog_predicate(type_ndarray:([])/3)'
ERROR: [Thread pce] prolog_predicate <-name: Argument 1 (name): `name' expected, found `[]'
% etc., etc.

and I have to kill the process.

So this is not exclusively related to atomic_list_concat but a predicate whose name is [] (a non-atom) clearly has wider issues.

Sure. I guess the idea is to fix library(prolog_code) and, if possible, reuse that from xpce. Please submit patches.

PR #1383 submitted. Patches library(prolog_code) and fixes by in new profiler default text output.

1 Like