I’m struggling to figure out what the use case is for enabling the unify port via visible/1 or leash/1. In all the cases I try, it seems to give you redundant information to the exit or fail ports for the same box.
Does anyone have a good example of when you need it when the other ports are visible?
I find that when helping new users learn Prolog that don’t fully understand how unification works, it helps to enable the unify port so that they can see when the unification occurred. Then in their head they can do the same unification and gain experience understanding unification.
If you use the Prolog Visualizer, which is a lot like a tracer and GUI tracer you will see that it also shows the unifications taking place, but also show the unifications that fail by crossing out the heads or facts after they fail.
Thanks @EricGT. Playing with some more complex examples I can see now that the exit or fail can come pretty far down the list of traces so having the unify trace can help orient you to which rule you are currently in.
Just so I understand: there isn’t really enough information in the traces to show which ones failed, right? You have to do a bunch of extra work like:
have an ordered list of all the heads for the rule being tried
remember the last one in the list that worked (i.e. sent a unify trace)
cross out all the heads in the list between the last success and the trace you just got by attempting to unify each with the trace. Presumably the ones that fail are the ones that got skipped
Just want to make sure I’m not missing a flag somewhere…
I want to give a definitive yes or no to that but I can’t. In general I would say yes.
In the following a head is either a head of a clause which has a head and body, or a fact with is a head without a body.
If I yes then I am thinking if one has the source code and knows that the order of the code decides the order of trying the unifications then you can infer which heads failed, but without the source code there is not enough detail in a trace to know a rule was tried and failed. This is what I like about the Prolog Visualizer. Another thing you have to remember is that with indexing the procedure to find the next head to check changes because with indexing you can index into a subset of the heads to check. I am not sure if that is why they call in indexing but the analogy works for me.
If I say no, then I am sure I could create a very simple example that did not need any additional info.
A few other things you have to be aware of when understanding a gtrace/0 are the icon such as builtin, dynamic, foreign, meta, etc. They are listed in the personal notes of this post.
Also note that with trace/0, ^ is for transparent predicates as noted here. I don’t have enough experience with SWI-Prolog to explain them. And with trace the numbers in parenthesis are referring to new frames, think recursion.
I did not know the details of those flags Jan W. gave in this answer until I read it.
My plan to write documentation for trace/0 and gtrace/0 was by starting at the source code and understanding every line, a bottom up approach, and why I took the time to find the location of the gtrace/0 icons. I knew if I had the locations of the source code with the icons that I was neck deep in the code used for debugging.
Indeed. It only show the unifications that succeed, not those that failed. It typically doesn’t really tries these either at it uses clause indexing to select possible candidates. The precise effect of clause indexing is hard to describe. In general the effect is that only a subset of the clauses are really tried, ignoring all those that definitely will not work.