Help me understand this syntax: *_

I love this tip from Markus Triska, who attributes it to Ulrich Neumerkel:

:- op(920,fy, *).


As a tool to isolate errors in code. But I don’t understand what the second specification is doing. After defining the unary operator, I would expect something like the following, to specify the semantics of the operator:


So what does the line without parens do?


1 Like

Have you seen these, they might be of some help?

“Declarative program development in Prolog” with GUPU by Ulrich Neumerkel and Stefan Kral (PDF)
“Localizing and explaining reasons for non-terminating logic programs with failure-slices” by Ulrich Neumerkel and Fred Mesnard (PDF)

While I am aware of the concept I don’t use it enough to answer more questions.

On StackOverflow see user false (Ulrich) and tag failure-slice.

FYI for those looking for where Markus notes the operator, see section Locating mistakes


As you’ve noted, the directive :- op(920, fy, *) defines * as an unary prefix operator. This precisely means that we can use * as a functor by putting it in front of other terms, without using the usual parentheses. So *_. is the same as * _. which is the same as *(_)., '*'(_)., etc.

?- op(920,fy, *).
?- write_canonical(*_).

I get it now. Thank you.

I looked on StackOverflow for failure-slice by Ulrich but didn’t see anything for *_ – did I miss something? (The papers look interesting, but will take some work for me to understand)

1 Like

This is where I saw the idea referenced: Debugging Prolog Programs

Seems clever and useful. I’ve started using this mechanism, as it’s smoother than commenting out.


That’s a good article. It introduces the concept of generalisation and specialisation of a logic program, or a definite clause, that is central to Logic Programming and to Inductive Logic Programming (ILP). In fact all ILP approaches work on the basis of this concept: they either start with a program that is over-general and specialise it, or with one that is over-special and generalise it, or do both in tandem. Like Markus points out, that is only possible in a logic programming language like Prolog where programs are sets of clauses and clauses are sets of literals, so changing the semantics of a program is a simple matter of adding or removing a literal or a clause; which is also what makes ILP computationally hard! Good stuff, Markus. And I see a reference to one of the two foundational texts of ILP, Ehud Shapiro’s doctoral thesis (Algorithmic Program Debugging).

See this for failure slicing:

also: program slicing - Selection sort in prolog - Stack Overflow

But specifically for *, it’s Triska’s video that explains the idea the best:

1 Like