I’ve been working on implementing dictionary support into swipl-rs. I really like dictionaries in SWI-Prolog, and we use them extensively in TerminusDB. However, it looks like the foreign function interface to dictionaries is somewhat restricted compared to what you can do from prolog itself. These are the differences I spotted.
- Dicts can have both atoms and small integers as keys. However, the ffi only supports atoms, both in construction through
PL_put_dict()
and in querying throughPL_get_dict_key()
. - A dict tag can be an arbitrary term (though it’s definitely ‘normal’ to have it be an atom). From the ffi, it can only be an atom.
- There is no destructive assignment (
b_set_dict
andnb_set_dict
in prolog). While a backtracking version would be tricky from the ffi, there is no reason why the non-backtracking version couldn’t exist. - There is no way to retrieve the tag of a dict.
- There is no way to iterate over all key-value pairs of a dict.
Regarding the last 3 points, I can probably implement that myself easily by just destructuring the dict term. While that would mean relying on the implementation details of dicts, I’m probably able to spot any upcoming changes to the implementation before they hit stable. Similarly, unifying the tag with an arbitrary term could also be done by destructuring a dict, after creating it with a var as a tag.
Supporting small integers as keys is more tricky though. The way things are now, that would require me to manually build the dict term, which means I have to sort the keys in the same way SWI-Prolog does it.
I understand that key-value pairs are sorted by key in the dict term, but they are not sorted as they would if you were to sort in prolog. Instead, they are sorted by some internal representation, which from experiments seems dependent on the underlying atom_t
value. However, I don’t really understand how this sort works when small integers are involved too. For any atom key, I’m able to devise, through trial and error, small integer keys that will appear before it, and small integer keys that will appear after it. So it would appear that the internal representation used by dictionary sorting has mapped both atoms and small integers into the same range. How exactly is this done, and is this something I could rely on myself to construct my own dict terms?