Some discussions are going on in the PIP working group related to synchronize (as a lightweight standardize) some aspects between Prolog systems. I’d like to seek opinions on a few things. Let me start with the relevant proposals and how I see this wrt. SWI-Prolog.
dicts/named arguments
ECLiPSe uses p{x:1, y:2} for what it calls struct, and Ciao calls this named arguments with a slightly different syntax. Either way, the idea is that we declare the argument names of a compound term, say :- struct p(x,y,z), after which a term p{k:v, ...} creates a compound term p(X,Y,Z) where every named argument is placed in the corresponding argument and other arguments of the compound are unbound. So, p{y:2} maps to p(_,2,_). The interpretation should ideally be handled by read/1.
This of course conflicts with SWI-Prolog’s dicts that use fully dynamic sets of keys. Now I have the impression that the “tag” (as in tag{}) is not used for much. People tend to use _ (anonymous variable). This matches anything, which you typically want. The drawback though is that makes the dict non-ground, while this is typically the intend. I started using #{...}, which is fine as long as you use it consistently.
We are moving towards a consensus that #{...} is a dynamic dict as SWI-Prolog uses them, the use of variables as tags is not allowed and any other atom refers to an argnames/struct as outlined above. I’m tempted to agree with that. I’d probably allow for any other atom to map to a current dynamic dict as long as there is no declaration for the argument names, with a flag to control this.
Attributed variable syntax
Somewhat related, ECLiPSe allows writing variables with attributes as Var{a1:v1, ...}. SWI-Prolog has what I always considered an obsolete option to write terms with attributed variables using this syntax, but reading would (now) produces a dict rather than a variable with attributes. SICStus inspired copy_term/3 is the way the Prolog toplevel handles constraints. If we stop allowing for _{k:v, ...} as dict syntax, we free up this syntax.
Cyclic term syntax
Stronger related, Joachim from ECLiPSe proposes to handle the result of e.g., X = f(X) as X{= : f(X)}. This generally allows to bind a term as you read it to a variable. I guess this also means you can write Y = f(X{= : p(1), X) which would be the same as X = p(1), Y = f(X,X).
This as opposed to what SWI-Prolog copied from SICStus, writing the result of X = f(X) as @(X, [X=f(X)]), i.e. a cyclic term is written as a term @(Skeleton,ListOfUnifications). The disadvantage is twofold. First, to get the real thing you need to rebind the unifications and second, terms @(X,Y) are ambiguous.
Note that @dmchurch has proposed (Inline subterm naming syntax (was: Syntax for unify-and-remember in head?)) to use (Var) term to mean the same as the proposal here Var{= : term}. (Var) term looks prettier, but I’m a little afraid of the ambiguities. Surely if term is a postfix operator, this is already valid syntax, but with different interpretation.
Opinions?
Notably, is this a good plan and if so, how should we deal with this to comply without introducing a big backward compatibility issue?