How it is possible that it is assigning a free to another free?
Your use of the word assigning
is telling us a secret about how you think about Prolog. When you see =
in Prolog, that is not assignment, but unification, see: =/2. Prolog works by unification or more specifically syntactic unification.
If Prolog can unify two free variables together, for example A
and B
and when one of them then becomes bound, the other is also bound at the same time because they were unified before.
While not entirely accurate, another way to think about this is as pointers.
If you start off with one pointer pointing to A
and a different pointer pointing to B
, which are different locations and latter find that A
and B
are unified, the pointers to both A
and B
will be adjusted to now point to the same location. However the location they point to is still an unbound location as neither A
or B
have a value. When either A
or B
are bound to a value, then they both become bound at the same time because the pointers are pointing to the same location.
Here is some test code the demonstrates the details.
test_01 :-
format('A: ~w~n',[A]),
format('B: ~w~n',[B]),
A = B,
format('A: ~w~n',[A]),
format('B: ~w~n',[B]),
A = 5,
format('A: ~w~n',[A]),
format('B: ~w~n',[B]).
Running this returns the following. I added the comments in after the fact by hand.
?- test_01.
A: _480 % Line 1
B: _486 % Line 2
A: _480 % line 3
B: _480 % line 4
A: 5 % Line 5
B: 5 % Line 6
true.
In line 1 the variable A
is internally referenced as an unbound variable: _480
In line 2 the variable B
is internally referenced as an unbound variable: _486
Note that _480
and _486
represents two different unbound variables.
Note that A
and B
are not internally referencing the same.
Next the code executes A = B
then
In line 3 the variable A
is internally referenced as _480
In line 4 the variable B
is internally referenced as _480
Note that now A
and B
are internally referencing the same: _480
.
Next the code executes A = 5
In line 5 the variable A
internally references _480
which is now bound with the value 5
.
In line 6 the variable B
internally references _480
which is now bound with the value 5
.
When this happened, there were not two separate bindings, but one binding to one location, which because of unification, and thus the reference to the same location, two variables became bound to a value with one action.
So when you see B = A, A = 2.
it is can mean that B
and A
were unified, (referencing the same location), and that the bound value in the location for B
is 2
, which is also the same bound value for B
since A
and B
were unified.
However in your specific example since Max
and Min
were never unified it is just the particular way the SWI-Prolog displays them.
I ran a trace of your example to see exactly what your were noting.
?- leash(-all),visible(+all),trace.
true.
[trace] ?- maxmin([2],Max,Min).
Call: (8) maxmin([2], _4408, _4410)
Unify: (8) maxmin([2], _4408, _4410)
Call: (9) maxmin([], 2, 2, _4408, _4410)
Unify: (9) maxmin([], 2, 2, _4408, _4410)
Call: (10) _4408 is 2
Exit: (10) 2 is 2
Call: (10) _4410 is 2
Exit: (10) 2 is 2
Exit: (9) maxmin([], 2, 2, 2, 2)
Exit: (8) maxmin([2], 2, 2)
Max = Min, Min = 2.
It might be that SWI-Prolog is keeping a table of display values and that it notices that both Max
and Min
have the same value so displays them that way, but I don't want to take the time to dig into the code find the details.
Is this some reflection stuff in Prolog I am not aware of?
I would not use the word Reflection to describe it.
Some test cases for your code. I used to make sure your code was working in case you had a bug and forgot to ask about it.
:- begin_tests(maxmin_tests).
maxmin_test_case([1],1,1).
maxmin_test_case([1,2],2,1).
maxmin_test_case([2,1],2,1).
maxmin_test_case([1,2,3],3,1).
maxmin_test_case([3,2,1],3,1).
maxmin_test_case([2,3,1],3,1).
maxmin_test_case([3,1,2],3,1).
test(1,[forall(maxmin_test_case(Input,Expected_max,Expected_min))]) :-
maxmin(Input,Max,Min),
assertion( Max == Expected_max ),
assertion( Min == Expected_min ).
test(2,[fail]) :-
maxmin([],_,_).
:- end_tests(maxmin_tests).
Example run
?- run_tests.
% PL-Unit: maxmin_tests ........ done
% All 8 tests passed
true.
Max = 2, Min = 2
. SWI does this for some reason. – Daniel LyonsMax = Min, Min = 2
then Max is also unified to2
. That's why it is called "unification" and not "assignment". – Enigmativitymaxmin
/3 has only one clause, and inmaxmin
/5 the pattern-matching on the first parameter will discriminate. There is no reason to useis
instead of=
unless you are evaluating mathematical expressions. – Tomas By