Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Variable Names in Prolog

698 views
Skip to first unread message

Nada Sharaf

unread,
Feb 20, 2012, 12:46:14 PM2/20/12
to
Hello all. I have a problem that since variable names are always
replaced with ones that start with _G I cannot know the mapping back.
So, is there a way to know that variable _G123 maps to X for example,
so that I can print X or write it to a file instead of having _G123
written.
Thank you very much

Feliks

unread,
Feb 20, 2012, 7:50:12 PM2/20/12
to
This is probably a little more complicated than what you want, but...

In SWI-Prolog (is that what you are using?) you can do
read_term( Term, [ variable_names( VarDict ) ] )
You can then call your own printing procedure that uses the names from
VarDict whenever it prints variables. I don't see a similar option in
write/2. :-(

The top level in SWI-Prolog will print your original variable names.
In general, many variables are created during the computation and just
don't have original names.

Hope this helps a little,
-- Feliks

Jan Wielemaker

unread,
Feb 21, 2012, 3:31:58 AM2/21/12
to
On 2012-02-21, Feliks <feliks....@utdallas.edu> wrote:
> On Feb 20, 11:46 am, Nada Sharaf <nada.shara...@gmail.com> wrote:
>> Hello all. I have a problem that since variable names are always
>> replaced with ones that start with _G I cannot know the mapping back.
>> So, is there a way to know that variable _G123 maps to X for example,
>> so that I can print X or write it to a file instead of having _G123
>> written.
>> Thank you very much
>
> This is probably a little more complicated than what you want, but...
>
> In SWI-Prolog (is that what you are using?) you can do
> read_term( Term, [ variable_names( VarDict ) ] )
> You can then call your own printing procedure that uses the names from
> VarDict whenever it prints variables. I don't see a similar option in
> write/2. :-(

Bind the variables to e.g., '$VAR'('VarName') and call write_term using
the option numbervars(true). That is what the toplevel does.

> The top level in SWI-Prolog will print your original variable names.
> In general, many variables are created during the computation and just
> don't have original names.

My gut feelings tell me that the OP doesn't understand some quite basic
Prolog principle, but I not sure which one ... E.g., are we talking
about toplevel query variables or program text variables?

Cheers --- Jan

Nada Sharaf

unread,
Feb 21, 2012, 6:01:45 AM2/21/12
to
Thanks a lot. I am aware that I can do it for reading terms. The
problem is that I do not want to read terms.

Jan Burse

unread,
Feb 21, 2012, 7:34:59 AM2/21/12
to
Hi,

Jan Wielemaker schrieb:
> Bind the variables to e.g., '$VAR'('VarName') and call write_term using
> the option numbervars(true). That is what the toplevel does.

Unfortunately '$VAR'('VarName') is not ISO, and is
neither widespread, since some other Prolog systems
use '$VAR'("VarName") or work with a write option.

Bye

Nada Sharaf

unread,
Feb 21, 2012, 8:56:30 AM2/21/12
to
On Feb 21, 10:31 am, Jan Wielemaker <j...@invalid.invalid> wrote:
Thanks a lot for the reply.
I have one issue however,
I am using the CHR library so when the user enters leq(A,B) for
example, I take this and I write it to a file for further processing.
However what is written is leq(_G123,_G124) for example.
As far as I understand, I have to bind the variables first before I
try to write them from within the CHR program, so for example if the
rule is cons(N) ==> write_term(cons(N),[numbervars(true)])|true.
then the query the user inserts should for example be
toplevel_variables:bind_vars([M='$VAR'('M')]),cons(M), in order to be
able to know the original variable names and bind them. I mean that
the user should do the binding while inserting the query because
otherwise there is no way to tell that N is actually 'M'.
Is this correct?
Thank you very much for your help

Jan Wielemaker

unread,
Feb 21, 2012, 9:06:22 AM2/21/12
to
But, ISO write_term/3 has an option numbervars(true), which means it
must write A for '$VAR'(0) (not really sure here; is $VAR mentioned in
the ISO document?). The step to making it write X for '$VAR'('X')
seems logical to me. Using "X" is a strange decision because the
other place using variable names also uses atoms (read_term).
Nevertheless, dealing with both would be feasible as a temporary
measure to fix portability.

Yes, using variable_names(['X'=_2341, ...]) is an alternative. It has
some merits. I'm not really convinced, but I'm happy to provide it if
we settle for that.

Cheers --- Jan

Nada Sharaf

unread,
Feb 21, 2012, 11:05:23 AM2/21/12
to
On Feb 21, 4:06 pm, Jan Wielemaker <j...@invalid.invalid> wrote:
Thank you very much for your help.
Actually, my issue now is with the place where
toplevel_variables:bind_vars should be used.
If my CHR rule is cons(N) ==> write_term(cons(N),[numbervars(true)])|
true. so within the rule I write the constraint, as far as I
understand bind_vars should be done when writing the goal or the
query. SO for example if the user types cons(M) then he/she should add
toplevel_variables:bind_vars([M='$VAR'('M')]) so that when the rule is
executed cons(M) is written.
Thank you very much

Nada Sharaf

unread,
Feb 21, 2012, 1:56:55 PM2/21/12
to
Since also toplevel_variables:bind_vars does not seem to work from
inside the program's code.
Thank you

Nada Sharaf

unread,
Feb 21, 2012, 4:10:26 PM2/21/12
to
On Feb 21, 4:06 pm, Jan Wielemaker <j...@invalid.invalid> wrote:
Hello How are you :)
I have been working for a while and I have reached a point where I can
extract the constraints from the term using the initial variable names
(Since I am using the CHR library). However, there seems to be a weird
general behavior with CHR regardless so I went back to try a simple
example to reach the problem and here is what I found.
First of all, this is the program I used (the leq handler)


:- use_module(library(chr)).
handler leq.
constraints leq/2.
reflexivity @ leq(X,X) <=> true.
antisymmetry @ leq(X,Y), leq(Y,X) <=> print('here'),nl, X = Y.
transitivity @ leq(X,Y), leq(Y,Z) ==> leq(X,Z).

Here are the attempts:

1 ?- leq(A,B),leq(B,C),leq(C,A).
here
here
A = B, B = C ;
false.

2 ?-
toplevel_variables:bind_vars([A='$VAR'('A')]),toplevel_variables:bind_vars([B='$VAR'('B')]),toplevel_variables:bind_vars([C='$VAR'('C')]),leq(A,B),leq(B,C),leq(C,A).
here
false.

So there seems to be a problem when using bind_vars while using the
constraints, one of them is ignored (and it could be noticed since
here was printed once instead of twice). I am correct or am I missing
out on something?

Thank you very much,
Nada


Jan Wielemaker

unread,
Feb 22, 2012, 3:46:26 AM2/22/12
to
On 2012-02-21, Nada Sharaf <nada.s...@gmail.com> wrote:
> I have been working for a while and I have reached a point where I can
> extract the constraints from the term using the initial variable names
> (Since I am using the CHR library). However, there seems to be a weird
> general behavior with CHR regardless so I went back to try a simple
> example to reach the problem and here is what I found.
> First of all, this is the program I used (the leq handler)
>
>
>:- use_module(library(chr)).
> handler leq.
> constraints leq/2.
> reflexivity @ leq(X,X) <=> true.
> antisymmetry @ leq(X,Y), leq(Y,X) <=> print('here'),nl, X = Y.
> transitivity @ leq(X,Y), leq(Y,Z) ==> leq(X,Z).
>
> Here are the attempts:
>
> 1 ?- leq(A,B),leq(B,C),leq(C,A).
> here
> here
> A = B, B = C ;
> false.

This seems to be completely fine with me. I still have no clue what
you try to achieve.

> 2 ?-
> toplevel_variables:bind_vars([A='$VAR'('A')]),toplevel_variables:bind_vars([B='$VAR'('B')]),toplevel_variables:bind_vars([C='$VAR'('C')]),leq(A,B),leq(B,C),leq(C,A).
> here
> false.

What is happening here? You are trying to call into the system code to
give names to variables before activating the constraints? That won't
work, because '$VAR'('A') is not a variable and CHR's game is based on
attributed variables, which needs variables to start with.

And anyway, why would you want that? At the end of the story you have
that A==B==C. In Prolog's internals, that means there is only one variable
left. So, what name does this variable have? 'A' or 'B' or 'C'?

What you can do is create an attribute, say name using

put_attr(A, name, 'A').

then you need to define an attribute unification hook that says what
must happen if two named variables unify, etc. Then you can fetch the
name using get_attr(Var, name, Name). I don't see much point in it, and
it may affect how the program behaves if the program queries the
presense of attributes. And still, note that after A = 'Hello World', the
term is simply 'Hello World'. There is no place to stort the information
that this atom has been a variable named 'A'.

In other words, Prolog isn't a set of variables with values, but it is
a set of terms that may start as `unknown' (i.e., variable) and these
may become known (integer, atom, compound, ...). You cannot ask a
non-var term `for which variable are you the value'.

Hope this helps (either understanding a misconception or in describing
what you really want).

Cheers --- Jan

Nada Sharaf

unread,
Feb 22, 2012, 9:08:56 AM2/22/12
to
On Feb 22, 10:46 am, Jan Wielemaker <j...@invalid.invalid> wrote:
Thank you very much for your reply and help.
This clarified a lot. But the thing is that it performed the
transitivity rule once and the antisymmetry rule one time too as shown
from the print statements.

:- use_module(library(chr)).
handler leq.
constraints leq/2.
reflexivity @ leq(X,X) <=> true.
antisymmetry @ leq(X,Y), leq(Y,X) <=> print('antisymmetry'),nl,
print('X is '),print(X), X = Y.
transitivity @ leq(X,Y), leq(Y,Z) ==>
print('transitivity'),nl,leq(X,Z).

1 ?-
toplevel_variables:bind_vars([A='$VAR'('A')]),toplevel_variables:bind_vars( [B='$VAR'('B')]),toplevel_variables:bind_vars([C='$VAR'('C')]),leq(A,B),leq(B,C),leq(C,A).
transitivity
antisymmetry
X is C
false.

Actually my problem is more general. As you can see I print(X) from
within the rule. If I do not use the variable binding the printing
results in _G123 for example. My question was generally of there is a
way to know that X maps back to C for example.
As far as I understand from your last solution. I should enter
something like put_attr(A, name, 'A') in the query. But the result is
also weird.

4 ?- put_attr(A, name, 'A'), put_attr(B, name, 'B'), put_attr(C,
name, 'C'),leq(A,B),leq(B,C),leq(C,A).
transitivity
antisymmetry
X is _G10464
ERROR: sort/2: Type error: `list' expected, found `C'

So my question is generally whether there is a way to do this :)

Jan Burse

unread,
Feb 22, 2012, 9:49:33 AM2/22/12
to
Nada Sharaf schrieb:
> :- use_module(library(chr)).
> handler leq.
> constraints leq/2.
> reflexivity @ leq(X,X)<=> true.
> antisymmetry @ leq(X,Y), leq(Y,X)<=> print('antisymmetry'),nl,
> print('X is '),print(X), X = Y.
> transitivity @ leq(X,Y), leq(Y,Z) ==>
> print('transitivity'),nl,leq(X,Z).

One user utility could be a print that uses the variable
names of the current outer query context. With break/0
etc.. there could be multiple query contexts, so it would
just use the most recent.

This print could have the following uses:
i) Print the answer substitution
ii) Print goals during debug
iii) Print bindings during debug

And a new use:
iv) Let the end user use it, if he wishes

Here are some example uses:

i) Print the answer substitution
--------------------------------

SWI Prolog 6.0.0: Ok
?- Y = f(X).
Y = f(X).

Jekejeke Prolog 0.9.2: Ok
?- Y = f(X).
Y = f(X)


ii) Print goals during debug
----------------------------

SSWI Prolog 6.0.0: ?Not provided? (with default
setting, maybe this can be changed)
?- trace.
true.
[trace] ?- Y=f(X), Z=g(T).
Call: (7) _G368=f(_G366) ? creep
Exit: (7) f(_G366)=f(_G366) ? creep
Call: (7) _G373=g(_G371) ? creep
Exit: (7) g(_G371)=g(_G371) ? creep

Jekejeke Prolog 0.9.2: Ok
?- trace.
Yes
?- Y=f(X), Z=g(T).
0 Call Y = f(X) ?
0 Exit f(X) = f(X) ?
0 Call Z = g(T) ?
0 Exit g(T) = g(T) ?
Y = f(X),
Z = g(T)


iii) Print bindings during debug
--------------------------------

SWI Prolog 6.0.0: ?Not provided? (didn't
find a debugger option in text mode for
showing bindings, but gtrace should do
something, but I am on Mac and gtrace
didn't work)

Jekejeke Prolog 0.9.2: Ok
?- Y=f(X), Z=g(T).
0 Call Y = f(X) ?b
Y = Y
X = X
0 Call Y = f(X) ?
0 Exit f(X) = f(X) ?b
Y = f(X)
X = X

iv) Let the end user use it, if he wishes
-----------------------------------------

SWI Prolog 6.0.0: ?Not provided? (don't
know how difficult it would be to implement
a corresponding print/1).

Jekejeke Prolog 0.9.2: Ok
?- Y=f(X), print('Current binding of Y is '), print(Y), nl.
Current binding of Y is f(X)
Y = f(X)


Best Regards


P.S.: Here is the code for the print utility:

/**
* Prolog code for the print utility. Requires version 0.9.2
* which has a debugger API.
*
* Need to recreate a clause frame, since a query frame
* might have incomplete variable bindings due to the
* body and head variable optimization. And we don't return
* variable names for potentially incomplete frames aka
* stack frames.
*
* For more information see:
*
http://www.jekejeke.ch/idatab/doclet/prod/en/docs/10_dev/02_reference/05_theories/02_debug/02_custom.html
*
* Copyright 2011, XLOG Technologies GmbH, Switzerland
* Jekejeke Prolog 0.9.2 (a fast and small prolog interpreter)
*/

% match_bindings(+List,+List)
match_bindings([],[]).
match_bindings([X|Y],[Z|T]) :- match_binding(X,Z), match_bindings(Y,T).

% match_binding(+Bind,+Bind)
match_binding(null,var(_)).
match_binding(var(X),var(X)).

% print(+Term)
print(X) :-
current_prolog_flag(sys_query_frame,F),
frame_property(F,sys_bindings(B)),
frame_property(F,sys_clause_ref(R)),
sys_instance_clause(R, G),
frame_property(G,sys_bindings(C)),
match_bindings(B,C),
frame_property(G,variable_names(N)), !,
write_term(X,[variable_names(N)]).
print(X) :- write(X).

Jan Wielemaker

unread,
Feb 22, 2012, 3:01:23 PM2/22/12
to
On 2012-02-22, Nada Sharaf <nada.s...@gmail.com> wrote:
>:- use_module(library(chr)).
> handler leq.
> constraints leq/2.
> reflexivity @ leq(X,X) <=> true.
> antisymmetry @ leq(X,Y), leq(Y,X) <=> print('antisymmetry'),nl,
> print('X is '),print(X), X = Y.
> transitivity @ leq(X,Y), leq(Y,Z) ==>
> print('transitivity'),nl,leq(X,Z).

What you really seem to be after is print(X), hoping that if X is the
same variable as the toplevel variable A, it prints "A". That is also
what Jan Burse is explaining for Jelejek Prolog. Yes, it is possible
to hack something like that. It looks nice in the examples he provides
because there is no program involved, so the only variable names that
matter are toplevel variables. However, we do the query

?- leq(X,Y), leq(Y,Z), leq(Z,X).

This is a pretty normal query. How confused will the users be if they
find out that print(VAR) prints the name of the toplevel variable, while
the clauses also give the variables names that are in the same X,Y,Z
domain, but the toplevel Y is the called X in the clause, etc.?

I think this is a dead end. I agree that _G232 is difficult to interpret.
The grahical tracer shows calls in their context using the variable names
from the context. That helps a little. What you're asking here is to
show variable names from a different context. That can't be right.

Cheers --- Jan

Nada Sharaf

unread,
Feb 22, 2012, 3:44:31 PM2/22/12
to
On Feb 22, 10:01 pm, Jan Wielemaker <j...@invalid.invalid> wrote:
Thank you very much for the reply. Actually, I need to know this
because I use the name in a Java class that I instantiate so, I was
hoping to be able to get the original variable name.
I am using SWI-Prolog. Is that possible for it? I searched in the
flags and I did not find ones similar to the ones used in Jelejek
Prolog.
May be I am missing out on something, but I do not understand why
would this be confusing to users and what you mean by "How confused
will the users be if they
find out that print(VAR) prints the name of the toplevel variable,
while
the clauses also give the variables names that are in the same X,Y,Z
domain, but the toplevel Y is the called X in the clause, etc.?"
Do you mean in the case that the variable names are the same in the
program and the query? I can ignore this case, but my question is
whether there is a way to know the original variable name.
For example if the program has the rule
leq(X,Y)=>print(X)|true.

then when I write the query
leq(A,B)
I get A printed not _G123 for example
So I would like print(X) to print the original variable name instead
of the one starting with _G123
Thank you very much

Jan Burse

unread,
Feb 22, 2012, 4:16:59 PM2/22/12
to
Jan Wielemaker schrieb:
> ?- leq(X,Y), leq(Y,Z), leq(Z,X).
>
> This is a pretty normal query. How confused will the users be if they
> find out that print(VAR) prints the name of the toplevel variable, while
> the clauses also give the variables names that are in the same X,Y,Z
> domain, but the toplevel Y is the called X in the clause, etc.?
>
> I think this is a dead end. I agree that _G232 is difficult to interpret.
> The grahical tracer shows calls in their context using the variable names
> from the context. That helps a little. What you're asking here is to
> show variable names from a different context. That can't be right.
>
> Cheers --- Jan

Yes, it is kind of confusing. And it takes some time to get
it right, respectively one needs to take some decision when
to display which name.

I am not sure how exactly gtrace works. Currently working on
a Mac, cannot verify. But there is a general problem with the
traditional Prolog loop in newer Prolog systems:

- You enter variables names in the top-level.
- They are not available as long as no
top solution is reached.
- Magically the top-level shows variable names
when a top solution is reached.

So in the old times we basically had:

?- X = Y.
X = _C,
Y = _C

Now some Prolog systems magically do the following:

?- X = Y.
X = Y

Maybe we can push some of this magic to other places. One
such place is the debugger. The ports are simple to do.
Just use the same routine as when writing answers. Here
is an example with recursion where new contexts are
created:

?- [user]
append([],X,X).
append([X|Y],Z,[X|T]) :- append(Y,Z,T).
^D
?- trace.
Yes
?- append([A,B],[C],R).
0 Call append([A, B], [C], R) ?
1 Call append([B], [C], _K) ?
2 Call append([], [C], _R) ?
2 Exit append([], [C], [C]) ?
1 Exit append([B], [C], [B, C]) ?
0 Exit append([A, B], [C], [A, B, C]) ?
R = [A, B, C]

In the above the variable names of the append/3 rules
do not appear. The _K and the _R are different versions
of the variable T in the second rule of append/3. But
T itself does not appear. This is how rule variables
appear via fresh variables only. Here fresh variables
have the format _@. One could also use the _G# format,
this is not that relevant.

In the curse of the execution of a top-level query
it can happen that goal invocations appear that have
fewer and fewer variables in common with the top-level
query. They will be all shown as fresh, and less magic
will be involved.

For the variable bindings inside a rule application,
something can be done that partially takes the rule
variables into account. It is tempting to write out
the bindings viewed from the variable names of the rule.

But the more simpler approach is to use the top-level
query variable names only on the right hand side of
the (=)/2 operator. And on the left hand side the rule
names. So that something as follows results:

?- append([A,B],[C],R).
0 Call append([A, B], [C], R) ?b
A = A
B = B
C = C
R = R
0 Call append([A, B], [C], R) ?
1 Call append([B], [C], _K) ?b
X = A
Y = [B]
Z = [C]
T = _K
1 Call append([B], [C], _K) ?
2 Call append([], [C], _R) ?b
X = B
Y = []
Z = [C]
T = _R
2 Call append([], [C], _R) ?
2 Exit append([], [C], [C]) ?b
X = B
Y = []
Z = [C]
T = [C]
2 Exit append([], [C], [C]) ?
1 Exit append([B], [C], [B, C]) ?b
X = A
Y = [B]
Z = [C]
T = [B, C]
1 Exit append([B], [C], [B, C]) ?
0 Exit append([A, B], [C], [A, B, C]) ?b
A = A
B = B
C = C
R = [A, B, C]
0 Exit append([A, B], [C], [A, B, C]) ?
R = [A, B, C]

In the above we see for example that _K
and _R where indeed versions of T. _R then
became [C] and _K then became [B, C]. The
binding display approach used above will
not shorten:

X = _C
Y = _C

To:

X = Y

Because this would violate our simple rule
to use the variable names from top-level query
on the right hand side of (=)/2. So for the
bindings of a clause when displayed during debugging
the end-user would need the old answer substitution
reasoning, to find out how the variables are actually
interconnected.

I was already thinking of an enhanced magic, that
would also use the variables names of the clauses
on the right hand side of (=)/2 when displaying
bindings during debugging. We could for example
use:

T' : first version of T
T'' : second version of T
Etc..

But not sure what the implications would be. And
not yet found an economic naming scheme. Don't want
to look at the 100-th version of T which would
be T'''''''''''''''''''''...... 100 times.

Bye

Jan Burse

unread,
Feb 22, 2012, 4:24:06 PM2/22/12
to
Jan Burse schrieb:
> Maybe we can push some of this magic to other places.

For the print/1 I agree, that eventually a different
predicate name should be chosen, so as not to break
other code.

Also in CHR the magic is even more useful. Since typically
rules do not introduce new variables so much, except
if one does fibonacci via CHR. (Right?)

I am currently thinking of:

show/1

Bye

Nada Sharaf

unread,
Feb 22, 2012, 4:31:25 PM2/22/12
to
Thank you very much for your help.
I actually need it for a CHR program that does not introduce new
variables as you said.
I eventually need to write the variable name into a file, so I was
hoping that there is a way to write the original name or the name that
the user has entered in the query instead of the one starting with _G
for example.

What I understand from your replies, is that there is currently no way
to do this from SWI-Prolog. Am I right?

Thanks you very much

Jan Burse

unread,
Feb 22, 2012, 4:48:25 PM2/22/12
to
Nada Sharaf schrieb:
> I actually need it for a CHR program that does not introduce new
> variables as you said.

Ok

> What I understand from your replies, is that there is currently no way
> to do this from SWI-Prolog. Am I right?

I cannot talk so much for SWI. I guess
some solution should be possible.

Hye

Jan Wielemaker

unread,
Feb 23, 2012, 10:03:21 AM2/23/12
to
On 2012-02-22, Nada Sharaf <nada.s...@gmail.com> wrote:
It still doesn't make much sense to me. But, unlike what you said,
you can use attributes to name your variables. First, load a module
holding this:

================================================================
:- module(varname,
[ set_var_name/2, % +Var, +Name
var_name/2 % @Term, -Name
]).

%% set_var_name(+Var, +Name) is det.

set_var_name(Var, Name) :-
put_attr(Var, varname, Name).

%% var_name(@Term, -Name) is semidet.
%
% True when Name is the name of Term.

var_name(Term, Name) :-
get_attr(Term, varname, Name).

% Two named variables are unified. Which name to keep?

attr_unify_hook(_Name, _Value).
================================================================

Now, your code:

================================================================
:- module(leq,
[ leq/2
]).
:- use_module(library(chr)).
:- use_module(varname).

:- chr_constraint leq/2.

reflexivity @ leq(X,X) <=> true.
antisymmetry @ leq(X,Y), leq(Y,X) <=> print_var(X),nl,
print('X is '),print(X), X = Y.
transitivity @ leq(X,Y), leq(Y,Z) ==> print_var(Y),nl,leq(X,Z).

print_var(Var) :-
var_name(Var, Name), !,
write(Name).
print_var(Var) :-
print(Var).

================================================================

Then load both into the toplevel, and do :-

?- set_var_name(A, 'A'), set_var_name(B, 'B'), set_var_name(C, 'C'),
leq(A,B),leq(B,C),leq(C,A).
B
C
X is _G53713B
X is _G53710
A = B, B = C,
put_attr(C, varname, 'A') ;
false.

Cheers --- Jan

Jan Wielemaker

unread,
Feb 23, 2012, 10:25:33 AM2/23/12
to
On 2012-02-22, Jan Burse <janb...@fastmail.fm> wrote:
> Jan Wielemaker schrieb:
>> ?- leq(X,Y), leq(Y,Z), leq(Z,X).
>>
>> This is a pretty normal query. How confused will the users be if they
>> find out that print(VAR) prints the name of the toplevel variable, while
>> the clauses also give the variables names that are in the same X,Y,Z
>> domain, but the toplevel Y is the called X in the clause, etc.?
>>
>> I think this is a dead end. I agree that _G232 is difficult to interpret.
>> The grahical tracer shows calls in their context using the variable names
>> from the context. That helps a little. What you're asking here is to
>> show variable names from a different context. That can't be right.
>>
>> Cheers --- Jan
>
> Yes, it is kind of confusing. And it takes some time to get
> it right, respectively one needs to take some decision when
> to display which name.
>
> I am not sure how exactly gtrace works. Currently working on
> a Mac, cannot verify. But there is a general problem with the
> traditional Prolog loop in newer Prolog systems:

Should work fine on the Mac. In Lion there don't seem to be many
X11 version issues, so the binary normally works. In older versions
you often have to install the right version of X11 or build Prolog
from source. I heard a rumour that the next version of MacOSX drops
X11 from the standard installation, so I fear that the nightmare will
soon be back :-(

Anyway, the graphical tracer provides three windows: the source,
the stack with choice-points and the bindings. The bindings is
a window with a list

VarName = Value,
...

Using the same logic as the toplevel for naming and dealing with
cycles and constraints, but using the variable names from the current
clause.

Printing the toplevel variables would get confusing here (unless,
maybe, we use some color-code to indicate that these names come
from elsewhere).

> For the variable bindings inside a rule application,
> something can be done that partially takes the rule
> variables into account. It is tempting to write out
> the bindings viewed from the variable names of the rule.

That is what the graphical tracer currently does. I think
that nicely shows how variables relate to each other.

> But the more simpler approach is to use the top-level
> query variable names only on the right hand side of
> the (=)/2 operator. And on the left hand side the rule
> names. So that something as follows results:

I guess that using the toplevel variables on the right make
sense on for the toplevel goals, but further down in the
trace, it will be rare that one of the toplevel variables
appears and showing the relations between the variables is
much more useful.

Cheers --- Jan

Jan Wielemaker

unread,
Feb 23, 2012, 10:29:32 AM2/23/12
to
On 2012-02-22, Jan Burse <janb...@fastmail.fm> wrote:
Not without changing some things. The simplest way to implement it
would be to make the variable names available through a global
variable set by the toplevel just before the query is started.
That isn't hard, but I still mostly see it as creating confusion
instead of reducing it.

Cheers --- Jan

Jan Burse

unread,
Feb 23, 2012, 10:56:48 AM2/23/12
to
Jan Wielemaker schrieb:
> % Two named variables are unified. Which name to keep?
>
> attr_unify_hook(_Name, _Value).

In the variable_names approach that I posted the
system will decided how to do the unification. If
there are two variables X1 and X2, and they are
different, either X1 will be instantiated by X2, or
X2 will be instantiated by X1.

Which one is taken is seen in the toplevel:

?- X = Y.

Either gives:

X = Y

Or:

Y = X

The variable names printing approach is such
that the write_term option variable_names takes
an arbirary list of name and term pairs:

vn_list :== [name = term|vn_list] | [].

The write routine will then first build a reverse
index (hash table, tree, etc.. data structure not
so important) of those terms that dereference
to a variable.

During the building of this index a choice is
take which variables will survive. For example
from the above query:

?- X = Y

We will have a variable name list:

['X' = _C, 'Y' = _C]

There are two possible indexes (typically
doomed by the order associations that are
given by the vn_list, but not necessarely):

[_C = 'X']

Or

[_C = 'Y']

And this is used in the toplevel to suppress
unnecessary bindings. So basically the top level
will not show which X1 is bound with which X2,
or vice versa. But how the index elected
variables.

This carries over to all application scenarios:

This print could have the following uses:
i) Print the answer substitution
ii) Print goals during debug
iii) Print bindings during debug

And a new use:
iv) Let the end user use it, if he wishes

Currently I am planning that the enduser can
inspect bindings along the call chain. The
current binding command is:

b = Binding

But eventually in release 0.9.3 there will
be a command of the form:

b<number> = Binding

This will show the binding of some of the
frames along the ancestors. Just going along
the frame parents <number> times to fetch the
right stack frame.

Since the query is the top frame, the end user
can also look at the top level variables even
when he is deep in some recursion. Deep in
some recursion, although when only fresh
variables are seen, they might inside a term
that has be instantiated with a query variable.

To summarize I see now 3 approaches:

A) $VAR('Name')
B) Name variable attributes
C) Variable Name List (vn_list in write_term
and vn_list as frame property, and query
frame as prolog flag)

Somehow A) and B) look to me quite intrusive.

- For A) if some constraint solving is in place, doing
X=$VAR() might fail.
- For B) this is less intrusive, but requires attribute
variables, not easy applicable to Prolog systems
without attribute variables.
- C) looks to me as the simplest approach. It is
invisible to the application logic.

Bye

Paulo Moura

unread,
Feb 23, 2012, 11:47:09 AM2/23/12
to
On Feb 23, 3:25 pm, Jan Wielemaker <j...@invalid.invalid> wrote:
>
> Should work fine on the Mac.  In Lion there don't seem to be many
> X11 version issues, so the binary normally works.  In older versions
> you often have to install the right version of X11 or build Prolog
> from source.  I heard a rumour that the next version of MacOSX drops
> X11 from the standard installation, so I fear that the nightmare will
> soon be back :-(

Users will need to install Xquartz. Even now, Xquartz already provides
a more up-to-date version of X11 than the installer bundled with Mac
OS X. In the developer preview of Mac OS X 10.8, trying to run an
application that requires X11 directs users to the Xquartz download
page (according to public available information).

Cheers,

Paulo

Jan Burse

unread,
Feb 23, 2012, 12:18:08 PM2/23/12
to
Paulo Moura schrieb:
I guess my problem is rather that I have an older mac,
respectively no backward compatibility of SWI Prolog?:

Mac OS X, Version 10.6.8

bash-3.2$ cd /opt/local/bin
bash-3.2$ PATH=$PATH:/opt/local/bin
bash-3.2$ echo $DISPLAY
/tmp/launch-aPvPXr/org.x:0
bash-3.2$ swipl
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 6.0.0)
Copyright (c) 1990-2011 University of Amsterdam, VU Amsterdam
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.

For help, use ?- help(Topic). or ?- apropos(Word).

?- gtrace.
ERROR: /opt/local/lib/swipl-6.0.0/xpce/prolog/boot/pce_principal.pl:141:
'$open_shared_object'/3:
dlopen(/opt/local/lib/swipl-6.0.0/lib/i386-darwin11.2.0/pl2xpce.dylib,
1): Library not loaded: /usr/X11/lib/libX11.6.dylib
Referenced from:
/opt/local/lib/swipl-6.0.0/lib/i386-darwin11.2.0/pl2xpce.dylib
Reason: Incompatible library version: pl2xpce.dylib requires version
10.0.0 or later, but libX11.6.dylib provides version 9.0.0

But I will check whether I can install a newer libX11.

Bye

Jan Burse

unread,
Feb 23, 2012, 1:45:34 PM2/23/12
to
Jan Burse schrieb:
>
> But I will check whether I can install a newer libX11.

Ok, a hack a day keeps the doctor away:

Installing XQuartz and in /usr:

rm X11R6
ln -s /opt/X11 X11R6
mv X11 X11old
ln -s /opt/X11 X11

does the job.

The stack gtrace, the bindings and everything, are
very cryptic when running:

?- append([A,B],[C],R).

But for example running:

?- append([a,b],[c],R).

Is comprehensible.

@Nada Sharaf:
Any particular reason you must run your program
with variables? Could you for testing not also
use atom arguments? This automatically solves
your problem...

So instead:

?- leq(A,B),leq(B,C),leq(C,A).

Maybe calling:

?- leq(a,b),leq(b,c),leq(c,a).

Would help? (I guess it doesn't help when the
arguments of leq are supposed to be constrained
variables and not values...)

Bye

Nada Sharaf

unread,
Feb 23, 2012, 1:39:33 PM2/23/12
to
On Feb 23, 5:29 pm, Jan Wielemaker <j...@invalid.invalid> wrote:
Thank you very much for your help and replies.
I have tried your first proposed method using a new module. Thank you
very much for providing it.

I have a question about your second solution regarding adding a global
variable to the toplevel. It is just because I have never done a
similar thing. Is this something that i can do. I mean can I change
the toplevel? I cannot imagine how I can do that, I have been going
through some different files in the boot folder of SWI but I am not
sure whether these are the right ones or whether I should be doing
this at all.

I just wanted to know what is provided currently and if there is a way
that it could be done with it. I can totally adjust my self to the
currently provided options. I can use the first approach if this
modification is not possible.
Thank you very much
Message has been deleted

Nada Sharaf

unread,
Feb 23, 2012, 2:03:45 PM2/23/12
to
On Feb 23, 5:29 pm, Jan Wielemaker <j...@invalid.invalid> wrote:
Hello again :)
As for using constants, then I can't add equalities because a=b
fails.
As for my last question I may have understood it the wrong way. Did
you mean by "Not without changing some things. The simplest way to
implement it
would be to make the variable names available through a global
variable set by the toplevel just before the query is started.
That isn't hard, but I still mostly see it as creating confusion
instead of reducing it. " the part where I add set_var_name(A, 'A'),
set_var_name(B, 'B'), set_var_name(C, 'C') to the query, then it is
totally fine. I got it :) I think I understood your last message in
the wrong way. I thought you meant adding something to the built-in
modules. That is why I got confused not knowing where to start.
Thank you very much

Jan Wielemaker

unread,
Feb 24, 2012, 11:32:12 AM2/24/12
to
On 2012-02-23, Jan Burse <janb...@fastmail.fm> wrote:
> The stack gtrace, the bindings and everything, are
> very cryptic when running:
>
> ?- append([A,B],[C],R).
>
> But for example running:
>
> ?- append([a,b],[c],R).
>
> Is comprehensible.

My guess is that the second case is far more common and
(as I claimed before) toplevel variables do not often
appear far down into the trace anyway. In other words,
I think that the solution to show clause-variables left
and toplevel variables right is only nice for quite
rare cases. It can be nice for some teaching scenarios
though.

Cheers --- Jan

Jan Wielemaker

unread,
Feb 24, 2012, 11:34:35 AM2/24/12
to
On 2012-02-23, Nada Sharaf <nada.s...@gmail.com> wrote:
> I have a question about your second solution regarding adding a global
> variable to the toplevel. It is just because I have never done a
> similar thing. Is this something that i can do. I mean can I change
> the toplevel? I cannot imagine how I can do that, I have been going

You have to edit boot/toplevel.pl and re-do the boot compilation. How
the latter is done depends a bit on the platform and whether you work
with a precompiled binary or compiled from source.

Cheers --- Jan

Nada Sharaf

unread,
Feb 24, 2012, 12:32:50 PM2/24/12
to
On Feb 24, 6:34 pm, Jan Wielemaker <j...@invalid.invalid> wrote:
Thank you very much. I have downloaded the binary version. It had the
executable files, I am using Windows 7. I will try with it.
Thanks a lot

Jan Burse

unread,
Feb 24, 2012, 1:08:20 PM2/24/12
to
Jan Wielemaker schrieb:
Yes, I still wonder why the CHR example needs to
be run with variables. Maybe somebody can explain?

Instead of a rule:

leq(X,Y), leq(Y,X) <=> X = Y.

I would expected something along:

leq(X,Y), leq(Y,X) <=> eq(X,Y).

Or:

leq(X,Y), leq(Y,X) <=> X = Y | true.

Etc...

But it is really a pitty that Prolog systems (due
to no support for top level variable naming) don't
match this presentation (*must read*):

http://dtai.cs.kuleuven.be/CHR/chr_by_example.shtml

First of all the example doesn't work with =<
in SWI, since =< is already defined. So I could
make it run with <=. So I tried the following:

?- [user].
:- use_module(library(chr)).
:- op(700,xfx,<=).
handler (<=).
constraints (<=)/2.
reflexivity @ X<=Y <=> X=Y | true.
antisymmetry @ X<=Y,Y<=X <=> X=Y.
transitivity @ X<=Y,Y<=Z ==> X<=Z.

?- A = B, B = C .

The article explains the result as simple as follows:

A=<B,C=<A,B=<C.
% C=<A,A=<B propagates C=<B by transitivity.
% C=<B,B=<C simplifies to B=C by antisymmetry.
% A=<B,C=<A simplifies to A=B by antisymmetry since B=C.
A=B,B=C.

This is the garble I get during trace:

Call: (7) _G28223<=_G28224 ? creep
CHR: (0) Insert: _G28223<=_G28224 # <141>
Exit: (7) _G28223{user = ...}<=_G28224{user = ...} ? creep
Call: (7) _G28226<=_G28223{user = ...} ? creep
CHR: (0) Insert: _G28226<=_G28223 # <142>
CHR: (2) Wake: _G28223<=_G28224 # <141> ? [creep]
CHR: (2) Redo: _G28223<=_G28224 # <141>
CHR: (1) Try: _G28226<=_G28223 # <142>, _G28223<=_G28224 # <141> ==>
_G28226<=_G28224.
CHR: (1) Apply: _G28226<=_G28223 # <142>, _G28223<=_G28224 # <141> ==>
_G28226<=_G28224. ? [creep]
CHR: (1) Insert: _G28226<=_G28224 # <143>
CHR: (3) Wake: _G28223<=_G28224 # <141> ? [creep]
CHR: (4) Wake: _G28223<=_G28223 # <142> ? [creep]
CHR: (4) Try: _G28223<=_G28223 # <142> <=> _G28223=_G28223 | true.
CHR: (4) Apply: _G28223<=_G28223 # <142> <=> _G28223=_G28223 | true. ?
[creep]
CHR: (4) Remove: _G28223<=_G28223 # <142>
CHR: (4) Redo: _G28223<=_G28223 # <142>
CHR: (3) Try: _G28223<=_G28224 # <141>, _G28224<=_G28223 # <142> <=>
_G28223=_G28224.
CHR: (3) Apply: _G28223<=_G28224 # <141>, _G28224<=_G28223 # <142> <=>
_G28223=_G28224. ? [creep]
CHR: (3) Remove: _G28224<=_G28223 # <142>
CHR: (3) Remove: _G28223<=_G28224 # <141>
CHR: (3) Redo: _G28224<=_G28224 # <141>
Exit: (7) _G28226{user = ...}<=_G28223{user = ...} ? creep
Call: (7) _G28224{user = ...}<=_G28226{user = ...} ? creep
CHR: (0) Insert: _G28224<=_G28226 # <144>
CHR: (2) Wake: _G28223<=_G28224 # <141> ? [creep]
CHR: (3) Wake: _G28223<=_G28223 # <142> ? [creep]
CHR: (3) Try: _G28223<=_G28223 # <142> <=> _G28223=_G28223 | true.
CHR: (3) Apply: _G28223<=_G28223 # <142> <=> _G28223=_G28223 | true. ?
[creep]
CHR: (3) Remove: _G28223<=_G28223 # <142>
CHR: (3) Wake: _G28223<=_G28223 # <143> ? [creep]
CHR: (3) Try: _G28223<=_G28223 # <143> <=> _G28223=_G28223 | true.
CHR: (3) Apply: _G28223<=_G28223 # <143> <=> _G28223=_G28223 | true. ?
[creep]
CHR: (3) Remove: _G28223<=_G28223 # <143>
CHR: (3) Redo: _G28223<=_G28223 # <143>
CHR: (3) Redo: _G28223<=_G28223 # <142>
CHR: (2) Try: _G28223<=_G28224 # <141>, _G28224<=_G28223 # <142> <=>
_G28223=_G28224.
CHR: (2) Apply: _G28223<=_G28224 # <141>, _G28224<=_G28223 # <142> <=>
_G28223=_G28224. ? [creep]
CHR: (2) Remove: _G28224<=_G28223 # <142>
CHR: (2) Remove: _G28223<=_G28224 # <141>
CHR: (2) Wake: _G28224<=_G28224 # <143> ? [creep]
CHR: (2) Try: _G28224<=_G28224 # <143> <=> _G28224=_G28224 | true.
CHR: (2) Apply: _G28224<=_G28224 # <143> <=> _G28224=_G28224 | true. ?
[creep]
CHR: (2) Remove: _G28224<=_G28224 # <143>
CHR: (2) Redo: _G28224<=_G28224 # <143>
CHR: (2) Redo: _G28224<=_G28224 # <141>
CHR: (1) Try: _G28224<=_G28226 # <144>, _G28226<=_G28224 # <143> <=>
_G28224=_G28226.
CHR: (1) Apply: _G28224<=_G28226 # <144>, _G28226<=_G28224 # <143> <=>
_G28224=_G28226. ? [creep]
CHR: (1) Remove: _G28226<=_G28224 # <143>
CHR: (1) Remove: _G28224<=_G28226 # <144>
CHR: (2) Wake: _G28223<=_G28224 # <141> ? [creep]
CHR: (3) Wake: _G28223<=_G28223 # <142> ? [creep]
CHR: (3) Try: _G28223<=_G28223 # <142> <=> _G28223=_G28223 | true.
CHR: (3) Apply: _G28223<=_G28223 # <142> <=> _G28223=_G28223 | true. ?
[creep]
CHR: (3) Remove: _G28223<=_G28223 # <142>
CHR: (3) Redo: _G28223<=_G28223 # <142>
CHR: (2) Try: _G28223<=_G28224 # <141>, _G28224<=_G28223 # <142> <=>
_G28223=_G28224.
CHR: (2) Apply: _G28223<=_G28224 # <141>, _G28224<=_G28223 # <142> <=>
_G28223=_G28224. ? [creep]
CHR: (2) Remove: _G28224<=_G28223 # <142>
CHR: (2) Remove: _G28223<=_G28224 # <141>
Exit: (7) _G28223<=_G28223 ? creep
A = B, B = C .

Maybe it wouldn't be that bad to do something against
it, as long as CHR has such a simple looking head mast
for advertising.

Bye





Jan Burse

unread,
Feb 24, 2012, 1:10:56 PM2/24/12
to
Correction:

Jan Burse schrieb:
> ?- A = B, B = C .

?- A<=B,C<=A,B<=C.

Jan Burse

unread,
Feb 24, 2012, 1:13:46 PM2/24/12
to
Jan Burse schrieb:
>
> This is the garble I get during trace:
>
> Call: (7) _G28223<=_G28224 ? creep

http://chr.informatik.uni-ulm.de/~webchr/

Does also not do it, refuses trace.

Bye
0 new messages