Bart Demoen made a petty criticism of between_aux/3 in my sample implementation of between/3. He continues: Conclusion: between_aux/3 is _not_ steadfast. The invariant that _your_ code imposes, can be violated by others in the same module. Steadfastness is all about the INTERFACE seen by USERS of modules. The point is that to the extent practical, users of Prolog modules should see predicates that act logically; when that doesn't make sense (predicates that are supposed to change the state, for example) they should still see predicates that are "clean" in whatever sense is appropriate.
It is entirely commonplace for modules in all sorts of languages to have internal operations which *could* do bad things but *don't* because the rest of the module ensures that they are never called in bad ways.
It is important that beween/3 should be steadfast, because it is an exported predicate.
It is important that between_aux/3 should be steadfast-in-context. For this purpose, it is idle chatter to talk about what other predicates in the module COULD do; they don't. Yes, a change to the module could introduce a bad call. But a change to the module could erase all the files on your disc.
The module this is drawn from is 99 SLOC. between_aux/3 (actually called between1/3 in the code) is *documented* as being an internal part of between/3 and aside from recursive calls is called in precisely one place. It is precisely as steadfast as it needs to be.
One thing I've often wished for in Prolog generally is the ability to make one or more predicates private to another predicate or predicates. In my early days at Edinburgh, I used to indent my code to depict the nesting that I would have liked.
In a functional language, I'd write let <local defs> in <public defs> end so let's rewrite between/3 like this:
:- let.
between_aux(L, U, X) :- ( L =:= U -> X = L ; X = L ; M is 1 + M, between_aux(M, U, X) ).
:- in.
between(L, U, X) :- ( integer(L), integer(U) -> ( integer(X) -> L =< X, X =< U ; var(X) -> L =< U, between_aux(L, U, X) ; <<diagnose and report type failure in X>> ) ; integer(L), var(U), integer(X), X < L -> fail ; integer(U), var(L), integer(X), X > U -> fail ; <<diagnose and report type error or instantiation fault>> ).
:- end.
Think of the :-let part as a "mini module" which can only be imported by the :-in part.
Let's look at the official definition of steadfastness, on page 96 of The Craft of Prolog:
'We want our predicates to be "constant, firm, unwavering" about giving the right answers; we call the property of refusing to give wrong answers even when the query has an unexpected form (typically, as here, supply values for what we normally think of as [outputs]) _steadfastness_ and say that a good predicate is _steadfast_.'
Yes, there's a typo in there. [outputs] reads 'inputs', which doesn't make sense. 'outputs' is what it _should_ say.
Now, since between_aux/3 is a private predicate of a module, ALL THE CALLS TO IT ARE KNOWN. Queries of "unexpected form" do not arise, so on a strict construal between_aux/3 is trivially steadfast.
If someone wants to get picky about whether an encapsulated predicate with only one call is "steadfast" according to some other definition, well, let them. It doesn't matter. The *point* of encapsulating things in modules is to give us the freedom to concentrate interface issues (like argument checking and steadfastness in general) in interface predicates, and to strip purely internal predicates to just the aspects they need to do their highly constrained job. ============================================================================== Message: Address: Action: help majordomo(a)clip.dia.fi.upm.es Info. on useful commands subscribe ciao-users-request(a)clip.dia.fi.upm.es Subscribe to this list unsubscribe ciao-users-request(a)clip.dia.fi.upm.es Unsubscribe from this list <whatever> ciao-users(a)clip.dia.fi.upm.es Send message to list ----------------------------------------------------------------------------- Archived messages: http://www.clip.dia.fi.upm.es/Mail/ciao-users/ -----------------------------------------------------------------------------