I’m trying parse dict query responses in the the foreign language interface.
In Prolog.h, I see we have the type ID PL_LIST and PL_get_list, and type id PL_DICT, but no PL_get_dict. Are dicts a functor?
Thanks in advance,
- Stuart
I’m trying parse dict query responses in the the foreign language interface.
In Prolog.h, I see we have the type ID PL_LIST and PL_get_list, and type id PL_DICT, but no PL_get_dict. Are dicts a functor?
Thanks in advance,
Seems I can indeed decode it as a functor.
Hmm…
Through the foreign API, I can get back:
?- A = point{x:1, y:2}
A = point{x:1, y:2}
But:
?- A = point{x:1, y:2}.x
returns:
A = .(point{'x': 1, 'y': 2}, x)
The retrieved term data is something like:
PL_FUNCTOR( =, A ,PL_FUNCTOR( . , PL_DICT(point, x, 1, y, 2 ), x ) )
Yet when I run the same query in the swipl command-line tool:
?- A = point{x:1,y:2}.x.
A = 1.
Does the swipl client unpack and apply the .x
, or is it done internally and I’m reading the data out through the API incorrectly?
Hmmm … this seems to be caused by the way pyswip executes querys, which is more or less:
pyrun(GoalString,BindingList) :-
(atom_chars(Z,GoalString),
atom_to_term(Z,Goal,BindingList),
call(Goal))).
Whereas normally, we’d get variables bound to values:
?- pyrun("fact(X)",BindingList).
BindingList = ['X'=123].
for the dict query we get:
?- pyrun("A = point{x:1,y:2}.x.", BindingList).
BindingList = ['A'=point{x:1, y:2}.x].
… with A not correctly unified with the value 1.
It seems wrapping execution inside this pyrun broke something. Breaking the query down:
?- atom_chars(Z__,"X=point{x:1, y:2}.x"), atom_to_term(Z__,Goal,BindingList), call(Goal).
Z__ = 'X=point{x:1, y:2}.x',
Goal = (point{x:1, y:2}.x=point{x:1, y:2}.x),
BindingList = ['X'=point{x:1, y:2}.x].
I thought perhaps call was incompatible with the dict syntax.
?- atom_chars(Z__,"X=point{x:1, y:2}.x"), atom_to_term(Z__,Goal,BindingList), X=point{x:1, y:2}.x.
Z__ = 'X=point{x:1, y:2}.x',
Goal = (_17164=point{x:1, y:2}.x),
BindingList = ['X'=_17164],
X = 1.
but the following works fine:
?- Goal = (X=point{x:1, y:2}.x), call(Goal).
Goal = (1=1),
X = 1.
… therefore, is some issue with the earlier part of the query?
Pwsip works this way because it makes it easy to load the PL_open_query()
call with the predicate name pyrun
, and the arguments list ["query_chars … ", ‘BindingList’). Without building the query the long-way, I don’t see a convenient way to execute dict querys via the foreign interface. Ideas?
The latest version comes with PL_get_dict_key() and a couple of more functions to deal with dicts from C. If your foreign interface does not support dicts the safest route is to do the dict <-> something translation in Prolog. Yes, dicts are compound terms, but there is no guarantee this never changes or the internal representation never changes (it did once already).
Hi @jan . Thank you. Separate to the foreign interface, the larger problem I’m having here is that the dot / .
operator for dict is interfering with atom_to_term
(I think):
?- atom_chars(Z,"X=point{x:1, y:2}.x"), atom_to_term(Z,Goal,BindingList), call(Goal).
Z = 'X=point{x:1, y:2}.x',
Goal = (point{x:1, y:2}.x=point{x:1, y:2}.x),
BindingList = ['X'=point{x:1, y:2}.x].
which doesn’t unify BindingList = ['X'=1]
as expected.
I’ll check out PL_get_dict_key once its in master (I assume its not in master yet, I don’t see similar functions here: https://github.com/SWI-Prolog/swipl/blob/6429a9cbdbca9cb807acc3c4fa40e7a67c08e4de/src/SWI-Prolog.h).
Dict evaluation is based on goal rewriting. That doesn’t happen in your code. See expand_goal/2.
It is in the development repository (swipl-devel.git) and already in the latest development release.
Worked perfectly. Thank you.