|
|
|
|
|
by falsissime
1151 days ago
|
|
Explicit checking of the appropriate instantiations is something for more or less official interfaces, not for every internal predicate. For those official checking via must_be/2, can_be/2 and the library(si) (all in Scryer) is often all you need. (The SWI-version conflates must_be/2 and can_be/2). But you could save your beloved cut with minimal effort by using dif_si/2 (voir https://stackoverflow.com/a/20238931/772868) just before the cut. In this manner you would get instantiation errors for exactly the cases you cannot handle. |
|
But there's no formal concept of "interface" in Prolog, and the module system sucks (or doesn't exist, depending on implementation) and many programs don't ever use it anyway, so instantiations errors are a possible issue at every level of a program. For me at least it's a constant headache knowning how a predicate must be called (hence my practice of documenting the structure of inputs and outputs carefully).
I really don't like the ad-hoc "type" checking in Prolog (as in integer/1 etc). Prolog doesn't have types, because pre-Church logic doesn't have types (and post-Church logic is a mess; typed mess, but still a mess). And yet Prolog terms (in the sense of a functor followed by comma-separated terms in parentheses) are implicitly typed, under unification: T is the type of all terms that unify with T. So making sure that terms are correctly instantiated is the most prudent thing to do when checking the "type" of a term. Unfortunately that adds too much clutter and I personally resent havng to do it. I have seen various attempts to solve that conundrum over the years, for example there's a package for SWI-Prolog that adds Hindley-Milner type checking (brrr). I don't like any of them.
It's a bit weird how that is the kind of thing that Prolog gets wrong that I rarely hear as an actual criticism, as opposed to complaints about the cut, or the imperfect declarative-ness.
I guess all this would be solved in practice by the addition of a static type system, checked at compile time, which would completely change the language of course. Incidentally, I'm currently working on an ancient (30 years old) Visual Prolog project; Visual Prolog is exactly that, a compiled Prolog with a static type system. I feel that while it sure helps catch some errors, it contrives to suck all the energy and life out of Prolog. Prolog is like parcour: it lets you fly around town, jumping and rolling like Spiderman. So sometimes you get a lamppost en plein dans la figure. So what. Who needs type safety anyway?
(She says while changing yet another bloody bandage)
>> But you could save your beloved cut with minimal effort by using dif_si/2 (voir https://stackoverflow.com/a/20238931/772868) just before the cut. In this manner you would get instantiation errors for exactly the cases you cannot handle.
Thanks for the pointer. I had a quick look. I think there's something similar in SWI-Prolog's Picat-style matching with the "=>" operator that is an alternative to ":-". I'm not sure exactly what it does (something about "steadfastness", that you also mentioned, and that is a new term for me) but I prefer to not use libraries that significantly change standard Prolog syntax, for fear of backwards compatibility.