I returned to Prolog and was happy to learn that Dicts are now available. They seem useful and I am trying to use them. So far they work like I expect, except with
For example, I was able to define this rule:
person2(Obj, Person) :-
When I tried
assert( (person2(Obj, Person):- member(Person, Obj.people)) ). it failed with “Arguments are not sufficiently instantiated”.
I was able to rewrite the assert in a clumsy way and it worked:
assert( (person2(Obj, Person):-
.(Obj, people, People),
member(Person, People)) ).
What was I doing wrong with the first
Assert doesn’t do term expansion and that is what sits between source code you
read and assert/1. So, you’d need to call expand_term/2 first. The more serious problem is that Obj.people will be evaluated when you try to expand/assert rather than at runtime. As code is data in Prolog, we do not know when we should evaluate. For short, the . notation only works for source code. Even there the expansion easily gets executed at the wrong moment when code is passed as in e.g. findall/3.
I don’t think that can be solved unless we have typing that tells us unambiguously when data is in fact code.
You can see what’s happening under the covers using listing/1. For example:
$ cat q.pl
assertion(A.foo == a).
$ swipl -q q.pl
'.'(A, foo, B),
When I re-loaded this (using make/0), I got the following, which is what I would have expected the first time. I’m guessing that this is because assertion/1 was auto-loaded and it has special term expansion hooks - when I added
:-use_module(library(debug)), the term expansion happened as expected. (Yet another unexpected subtlety in term-expansion …)
assertion(( '.'(A, foo, B),