Why is Prolog unifying a free variable to another free?Two stars in a Prolog listWhy is this prolog query both true and false?How do return both a variable result and a true/false in Prolog?SWI-Prolog - show long listProlog anonymous variableHow to use variables in Prolog query shell?Prolog VariableProlog nth1 anonymous variablesWhy does Prolog predicate member/2 print an extra whitespace in output?Why it doesn't unify? prolog
Did I make a mistake by ccing email to boss to others?
Are Captain Marvel's powers affected by Thanos breaking the Tesseract and claiming the stone?
The Digit Triangles
Showing mass murder in a kid's book
Given this phrasing in the lease, when should I pay my rent?
I'm just a whisper. Who am I?
Air travel with refrigerated insulin
Overlapping circles covering polygon
How do I prevent inappropriate ads from appearing in my game?
What the heck is gets(stdin) on site coderbyte?
How to I force windows to use a specific version of SQLCMD?
Why didn’t Eve recognize the little cockroach as a living organism?
Why would five hundred and five be same as one?
Typing CO_2 easily
Is there anyway, I can have two passwords for my wi-fi
Is there a reason to prefer HFS+ over APFS for disk images in High Sierra and/or Mojave?
Deciphering cause of death?
How do you justify more code being written by following clean code practices?
Storage of electrolytic capacitors - how long?
How can I, as DM, avoid the Conga Line of Death occurring when implementing some form of flanking rule?
Do I have to take mana from my deck or hand when tapping a dual land?
Telemetry for feature health
How to test the sharpness of a knife?
Why does the Persian emissary display a string of crowned skulls?
Why is Prolog unifying a free variable to another free?
Two stars in a Prolog listWhy is this prolog query both true and false?How do return both a variable result and a true/false in Prolog?SWI-Prolog - show long listProlog anonymous variableHow to use variables in Prolog query shell?Prolog VariableProlog nth1 anonymous variablesWhy does Prolog predicate member/2 print an extra whitespace in output?Why it doesn't unify? prolog
maxmin([X|L], Max, Min) :-
maxmin(L, X, X, Max, Min),
!.
maxmin([], CurrentMax, CurrentMin, Max, Min) :-
Max is CurrentMax,
Min is CurrentMin,
!.
maxmin([X|L], CurrentMax, CurrentMin, Max, Min) :-
CurrentMax2 is max(X, CurrentMax),
CurrentMin2 is min(X, CurrentMin),
maxmin(L, CurrentMax2, CurrentMin2, Max, Min).
Upon performing the query ?- maxmin([2],Max,Min).
, it will return Max = Min, Min = 2.
.
Why? I have several variation of this and none of them seems to work. How it is possible that it is assigning a free to another free? Is this some reflection stuff in Prolog I am not aware of?
Tracing does not show anything particularly interesting either. Namely, it exits from Exit: (8) maxmin([2], 2, 2) ? creep
which looks perfectly fine to me. This will only happen when I have a list of 1.
I am obviously not understanding Prolog but I can't figure out for the life of me where I am wrong. Any pointers?
prolog swi-prolog prolog-toplevel
add a comment |
maxmin([X|L], Max, Min) :-
maxmin(L, X, X, Max, Min),
!.
maxmin([], CurrentMax, CurrentMin, Max, Min) :-
Max is CurrentMax,
Min is CurrentMin,
!.
maxmin([X|L], CurrentMax, CurrentMin, Max, Min) :-
CurrentMax2 is max(X, CurrentMax),
CurrentMin2 is min(X, CurrentMin),
maxmin(L, CurrentMax2, CurrentMin2, Max, Min).
Upon performing the query ?- maxmin([2],Max,Min).
, it will return Max = Min, Min = 2.
.
Why? I have several variation of this and none of them seems to work. How it is possible that it is assigning a free to another free? Is this some reflection stuff in Prolog I am not aware of?
Tracing does not show anything particularly interesting either. Namely, it exits from Exit: (8) maxmin([2], 2, 2) ? creep
which looks perfectly fine to me. This will only happen when I have a list of 1.
I am obviously not understanding Prolog but I can't figure out for the life of me where I am wrong. Any pointers?
prolog swi-prolog prolog-toplevel
2
It's saying Max and Min are both bound to 2. It would be no different if it saidMax = 2, Min = 2
. SWI does this for some reason.
– Daniel Lyons
Mar 7 at 5:56
@Hanif Bin Ariffin Prolog makes a variable chain - the last variable will reffer to value.
– Anton Danilov
Mar 7 at 5:57
1
In Prolog if you haveMax = Min, Min = 2
then Max is also unified to2
. That's why it is called "unification" and not "assignment".
– Enigmativity
Mar 7 at 9:09
1
Maybe you could explain how it does not work, as it seems to make sense. Both the maximum and minimum of a list of one will be that one value. Your cuts are pointless:maxmin
/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
Mar 7 at 11:10
add a comment |
maxmin([X|L], Max, Min) :-
maxmin(L, X, X, Max, Min),
!.
maxmin([], CurrentMax, CurrentMin, Max, Min) :-
Max is CurrentMax,
Min is CurrentMin,
!.
maxmin([X|L], CurrentMax, CurrentMin, Max, Min) :-
CurrentMax2 is max(X, CurrentMax),
CurrentMin2 is min(X, CurrentMin),
maxmin(L, CurrentMax2, CurrentMin2, Max, Min).
Upon performing the query ?- maxmin([2],Max,Min).
, it will return Max = Min, Min = 2.
.
Why? I have several variation of this and none of them seems to work. How it is possible that it is assigning a free to another free? Is this some reflection stuff in Prolog I am not aware of?
Tracing does not show anything particularly interesting either. Namely, it exits from Exit: (8) maxmin([2], 2, 2) ? creep
which looks perfectly fine to me. This will only happen when I have a list of 1.
I am obviously not understanding Prolog but I can't figure out for the life of me where I am wrong. Any pointers?
prolog swi-prolog prolog-toplevel
maxmin([X|L], Max, Min) :-
maxmin(L, X, X, Max, Min),
!.
maxmin([], CurrentMax, CurrentMin, Max, Min) :-
Max is CurrentMax,
Min is CurrentMin,
!.
maxmin([X|L], CurrentMax, CurrentMin, Max, Min) :-
CurrentMax2 is max(X, CurrentMax),
CurrentMin2 is min(X, CurrentMin),
maxmin(L, CurrentMax2, CurrentMin2, Max, Min).
Upon performing the query ?- maxmin([2],Max,Min).
, it will return Max = Min, Min = 2.
.
Why? I have several variation of this and none of them seems to work. How it is possible that it is assigning a free to another free? Is this some reflection stuff in Prolog I am not aware of?
Tracing does not show anything particularly interesting either. Namely, it exits from Exit: (8) maxmin([2], 2, 2) ? creep
which looks perfectly fine to me. This will only happen when I have a list of 1.
I am obviously not understanding Prolog but I can't figure out for the life of me where I am wrong. Any pointers?
prolog swi-prolog prolog-toplevel
prolog swi-prolog prolog-toplevel
edited Mar 7 at 9:06
repeat
16.2k443139
16.2k443139
asked Mar 7 at 2:28
Hanif Bin AriffinHanif Bin Ariffin
707
707
2
It's saying Max and Min are both bound to 2. It would be no different if it saidMax = 2, Min = 2
. SWI does this for some reason.
– Daniel Lyons
Mar 7 at 5:56
@Hanif Bin Ariffin Prolog makes a variable chain - the last variable will reffer to value.
– Anton Danilov
Mar 7 at 5:57
1
In Prolog if you haveMax = Min, Min = 2
then Max is also unified to2
. That's why it is called "unification" and not "assignment".
– Enigmativity
Mar 7 at 9:09
1
Maybe you could explain how it does not work, as it seems to make sense. Both the maximum and minimum of a list of one will be that one value. Your cuts are pointless:maxmin
/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
Mar 7 at 11:10
add a comment |
2
It's saying Max and Min are both bound to 2. It would be no different if it saidMax = 2, Min = 2
. SWI does this for some reason.
– Daniel Lyons
Mar 7 at 5:56
@Hanif Bin Ariffin Prolog makes a variable chain - the last variable will reffer to value.
– Anton Danilov
Mar 7 at 5:57
1
In Prolog if you haveMax = Min, Min = 2
then Max is also unified to2
. That's why it is called "unification" and not "assignment".
– Enigmativity
Mar 7 at 9:09
1
Maybe you could explain how it does not work, as it seems to make sense. Both the maximum and minimum of a list of one will be that one value. Your cuts are pointless:maxmin
/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
Mar 7 at 11:10
2
2
It's saying Max and Min are both bound to 2. It would be no different if it said
Max = 2, Min = 2
. SWI does this for some reason.– Daniel Lyons
Mar 7 at 5:56
It's saying Max and Min are both bound to 2. It would be no different if it said
Max = 2, Min = 2
. SWI does this for some reason.– Daniel Lyons
Mar 7 at 5:56
@Hanif Bin Ariffin Prolog makes a variable chain - the last variable will reffer to value.
– Anton Danilov
Mar 7 at 5:57
@Hanif Bin Ariffin Prolog makes a variable chain - the last variable will reffer to value.
– Anton Danilov
Mar 7 at 5:57
1
1
In Prolog if you have
Max = Min, Min = 2
then Max is also unified to 2
. That's why it is called "unification" and not "assignment".– Enigmativity
Mar 7 at 9:09
In Prolog if you have
Max = Min, Min = 2
then Max is also unified to 2
. That's why it is called "unification" and not "assignment".– Enigmativity
Mar 7 at 9:09
1
1
Maybe you could explain how it does not work, as it seems to make sense. Both the maximum and minimum of a list of one will be that one value. Your cuts are pointless:
maxmin
/3 has only one clause, and in maxmin
/5 the pattern-matching on the first parameter will discriminate. There is no reason to use is
instead of =
unless you are evaluating mathematical expressions.– Tomas By
Mar 7 at 11:10
Maybe you could explain how it does not work, as it seems to make sense. Both the maximum and minimum of a list of one will be that one value. Your cuts are pointless:
maxmin
/3 has only one clause, and in maxmin
/5 the pattern-matching on the first parameter will discriminate. There is no reason to use is
instead of =
unless you are evaluating mathematical expressions.– Tomas By
Mar 7 at 11:10
add a comment |
1 Answer
1
active
oldest
votes
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.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55035126%2fwhy-is-prolog-unifying-a-free-variable-to-another-free%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
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.
add a comment |
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.
add a comment |
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.
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.
edited Mar 9 at 10:28
answered Mar 7 at 10:46
Guy CoderGuy Coder
16.1k44287
16.1k44287
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55035126%2fwhy-is-prolog-unifying-a-free-variable-to-another-free%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
It's saying Max and Min are both bound to 2. It would be no different if it said
Max = 2, Min = 2
. SWI does this for some reason.– Daniel Lyons
Mar 7 at 5:56
@Hanif Bin Ariffin Prolog makes a variable chain - the last variable will reffer to value.
– Anton Danilov
Mar 7 at 5:57
1
In Prolog if you have
Max = Min, Min = 2
then Max is also unified to2
. That's why it is called "unification" and not "assignment".– Enigmativity
Mar 7 at 9:09
1
Maybe you could explain how it does not work, as it seems to make sense. Both the maximum and minimum of a list of one will be that one value. Your cuts are pointless:
maxmin
/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
Mar 7 at 11:10