Subject: Re: handling small numbers

From: "Richard A. O'Keefe" <[email-masked]>
Date: Fri, 12 May 2000 11:50:02 +1200 (NZST)

Patrick Herring <[email-masked]> wrote:
	Yes, and this is very important for getting Prolog into data processing, 
	where it should have been from the first. Commercial systems are as much 
	about risk management as producing results, and silent errors are one of 
	the few things that can kill a project instantly. What does IBM's Prolog 
	do?
	
IBM PROLOG for 370 Language Reference Version 1 Release 1

p 334	term_assert(pragma, Option, Value)
	term_put(pragma, Option, Value)
	term_get(pragma, Option, Value), or
	term_protect(pragma, Option, Value)

	The values of these options can be undone by backtracking
	if the value of a given option has been set with term_put.

p 335	comp_exp_error (takes values 0 or 1)
	When the value is 0, computable expressions which cannot be
	evaluated produce an error.
	If the value is 1, a fail occurs.

	The default value is ZERO, that is, errors are reported.
	However, this manual is really rather vague about quite a
	number of points (when I did the IBM PROLOG to Quintus Prolog
	translator, I ran into quite a few of these).  In particular,
	the examples given seem to be precondition violations (syntax).

	However, I can find nothing in the manual to licence quiet
	conversion of rationals (including integers) to floats
	*except in comparison and unification* and then *not by default*.

p 336	fuzzvalue (value is a floating point numnber, it's like []CT)
	Specifies the precision to which two floating-point numbers
	must agree to be considered equal.
	[This has the nasty effect that unification is not transitive
	 in IBM's dialect.]

p 337	int_float (takes values 0, 1, or 2)
	Introduced for compatibility with VM/PROLOG.

	If the value of this option is 0, a float and a rational
	number cannot be unified, and for the full ordering of
	terms, a floating-point number is always bigger than a
	rational number.

	If the value of this option is 1, a float and a rational
	cannot be unified, and for the full ordering of terms,
	rationals are converted to floating-points for comparison.
	[They got this one wrong.  Common Lisp was *going* to do
	this until I pointed out that it would not be consistent.[
	it is necessary to convert floats to rationals!]
	In this case floats and rationals can never be evaluated
	as equal.

	If the value of this option is 2, a float and a rational
	number can be unified, and for the full ordering of terms,
	the comparison of a float is made by converting the
	rational to a floating-point number.  In this case, the
	full compiler may generate less compact code than when the
	value is 0 or 1.
	
	Note: the values of the pragma int_float at consult time
	and run time are expected to be compatible (both 2 or both
	belonging to the set {0,1}).  If the value of this pragma
	is changed between consulting a program and running it,
	the value of the pragma int_float used to run this program
	is unpredictable.

The problem with allowing rationals to be converted quietly to floats
in comparison and unification is that it is far too easy to find two
rationals P, Q (even two integers, if integers are 64 bits or floats
are 32) and a float X such that P = X, X = Q, but P < Q.  You can
even find numbers such that P =< X, X =< Q, but P > Q.  Someone
raised the issue of "using Prolog as a logic", well, if you want to
do _that_, you really want comparisons to work correctly!

IBM PROLOG had a lot of good features, including suspension (but not as well
as NU Prolog).  The main problem was that it had *too many* options, so that
when I tried to write a translator from IBM PROLOG to Quintus Prolog, it was
quite impossible to discover what IBM PROLOG syntax actually was, for the
simple reason that there wasn't any such animal.  There was a large _family_
of IBM Prolog syntaxes.  Try writing a library file that could be loaded
*whatever* the syntax flags were!  And even with fixed syntax, how could
you write a library file that would *run* under all of the hundreds of
possible run-time "dialects"?  If it wasn't for the undo-on-backtrack
behaviour of term_put, it would have been practically impossible, instead
of merely tediously awkward.

	>Been there, done that.  The `unknown' flag in some Prologs controls
	>what happens when you call an undefined predicate.  People soon
	>learned to switch
	>it onto the exception setting and *leave* it there all the time.
	
	Doesn't this muck up negation by failure, or have I completely 
	misunderstood what you're referring to?
	
No, it doesn't muck up negation as failure, not unless you put in
unknown/2 and leave out :- dynamic.  In DEC-10 Prolog and PDP-11 Prolog
(and some more recent ones), there was no difference between a predicate
that didn't *exist* and a predicate that had *no clauses*.  That did
limit the usefulness of unknown/2.

In later .edai versions of C Prolog that was fixed, as it was in Quintus
Prolog, with the :-dynamic declaration.  The :-dynamic declaration tells
the Prolog system "whether or not this predicate *has clauses*, it
none-the-less *exists*". If you use retractall/1 to remove all the
clauses of a dynamic predicate, it still *exists*. Only if you used
abolish/[1,2] to completely erase all the information about a predicate
did it cease to exist.