Subject: Re: handling small numbers

From: Paul Sephton <[email-masked]>
Date: Tue, 9 May 2000 14:22:50 +0200 (GMT+0200)

On Tue, 9 May 2000, Richard A. O'Keefe wrote:

> Paul Sephton <[email-masked]> wrote:
> 	How about simply using the languages inherent properties, and simply 
> 	failing the goal?  After all, if the programmer knows that the integer 
> 	representation has a maximum of 32 bits and happens to produce a larger 
> 	number, that is what I would like to expect.
> 	
> I discussed this in some detail in my 1984 Edinburgh paper.
> The point is that it is a *WRONG* answer.

It's not a wrong answer if you fail the goal- it's no answer at all 
within the confines of the implementation.  Were one to implement 
arbitrary integer arithmetic within the compiler/interpreter, that 
would be great, but hardly a requirement to sufficiently define the 
language.

> The key idea is Dijkstra's notion that we write a program for
> a "Sufficiently Large" abstract machine.
> We don't _have_ Sufficiently Large real machines.
> What we _can_ have is "Hopefully Sufficiently Large" machines
> which either give us the right answer or *tell* us they couldn't
> give us the right answer.
> 
> Now, if I write in a Prolog program
> 
> 	(I = 2147483647, J is I + 1)
> 
> then the answer "no" is *WRONG*; there really truly *does* exist a
> solution to that query.  It is just that there is a defect in the
> implementation such that the implementation cannot represent the
> correct answer.  In my exception handling design for Quintus, I
> classified exceptions into 16 categories; this one I called a
> "representation fault", and there are lots more of them.

Would it not be more sensible to give the programmer the choice as to 
whether he wants to use the exception mechanism to find out what the 
reason was that the goal failed?  Perhaps under some circumstances, a 
general failure is quite acceptible, whereas sometimes one needs to know 
the precise nature of the failure.

Just coming back to my example of the number_chars/2 predicate-  I really 
don't care that the predicate fails due to a "representation error", only 
that whatever it was I was trying to convert was not a valid 
representation for a number.  I would like to treat this as a simple 
failure of the goal and move on to the next goal.

> 	Silently promoting to a float has a lot of advantages-
> 
> except the advantage of giving you correct answers.  In the context
> of this specific thread, it has the very nasty disadvantage of
> *quietly* reintroducing the very roundoff problems that the use of
> integer arithmetic was supposed to avoid.

My attitude as stated above, is that sometimes it is perhaps not entirely 
accurate, but "good enough".  I come from a scientific background myself, 
but for the last 15 years have been programming in a commercial world.  
So I do understand your argument as well.  However, there should be a 
"default" behaviour and an "explicit" behaviour, if one is to implement a 
clean or non-intrusive exception mechanism.  I like the ability to 
silently promote integers, but don't think it should be the default 
behaviour (as I stated previously). 

Simply, the way I think things should work here, would be for integer 
promotion to be an optional feature.  With it, one would not be 
guaranteed absolute accuracy, but would have the benifit of having all of 
your hair after reading the source code.

Without the feature, one may still retain ones hair whilst accepting that 
integer overflow would cause the goal to fail normally, resulting in a retry.

To make provision for _explicitely_ handling overflows, or other arithmetic 
exceptions, one would have the availability of the exception handling 
mechanism.

> 	Likewise, exceptions generated by overflows/underflows ( or anything else 
> 	for that matter) can be a real pain in the neck, and as I have pointed 
> 	out, the language can manage quite well without this:
> 	
> Yes, but programmers can't.
> "Your query doesn't HAVE any answer"
> and
> "Your query may have an answer but I'm too limited to find it"
> are different statements demanding different responses from the programmer.

Yes, you are right of course.  But programmers _should_ be able (and 
allowed) to use their alleged intelligence to decide whether or not it 
matters that the query has an answer which the implementation is too 
limited to provide.

> Note that IEEE arithmetic defines floating-point overflow away, so
> 
> 	go(X) :-
> 	  X is VeryBigNumber1 * VeryBigNumber2.
> 	go(_) :-
> 	  writef('Sorry- cannot seem to get the answer\n').
> 	
> WOULD NOT WORK AS INTENDED in an IEEE-using Prolog.  You would have to
> write
> 	go(X) :-
> 	    Y is VeryBigNumber1 * VeryBigNumber2,
> 	    (   finite(Y) -> X = Y
> 	    ;   write('Sorry:  answer is not representable.'), nl
> 	    ).

Yes, I am well aware of this.  Again, for all practical purposes, it 
often does not matter.  But you misunderstand what I was intending to 
convey- 

My example was assuming your "non-promotion of integers" stance, but 
without the apparently consequent need for the introduction of an 
implicit exception handling mechanism.  Therefore, the overflow would 
occur in the first goal, resulting in that goal failing and backtracking 
to the second.  So, in fact where VeryBigNumber is an integer, my example 
is perfectly valid ( or should be in my perfect world ).

> No, it isn't.  Exceptions are *non-local* transfers of control;
> backtracking in Prolog is entirely local.

..and therefore essential and good?
In my opinion a goal that fails and backtracks is just another example of 
an exception- ok, not your idea of an exception, but nevertheless.

Paul
_____________________________________________________________________________
Paul Sephton ([email-masked])                               INET Development
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ever wondered if jumping out of the frying pan might actually be refreshing?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~