Support questions of general interest

From time to time, we report on customer questions and problem reports which might be of interest to users in general. Here are some things that came up during 2011.

1. Date validation in date-time calculations

Allegro CL supports ISO 8601 date-time representations, as described in date-time.htm. A user noted the following:

(require :datetime)
(use-package :util.date-time)

cl-user(9): (date-time "2011-02-30")
#<date-time "2011-02-30" @ #x476647a>
cl-user(10): 

That is, the date-time function accepted a bogus input (there is no February 30th in 2011 or any other year), and returned a bogus value. Actually, the user reported slightly different behavior:

cl-user(11) (ut-to-date-time (date-time-to-ut (date-time "2011-02-30")))
#<date-time "2011-03-02T00:00:00+01:00" @ #x22d8368a>

date-time-to-ut converts a date-time object to a universal time, and ut-to-date-time changes a universal time to a date-time object. The first of those functions accepted the date-time object which was a bogus date and converted to a universal time. When that universal time was reconverted to a date-time object, it returned a valid date (March 2, 2011) more or less corresponding to Feb. 30, 2011.

The user asked why we did not signal an error, either when the first date-time object was calculated, or when that value was passed to date-time-to-ut.

The answer we gave to the user and repeat here is doing so would slow down every call to date-time (or date-time-to-ut or both). There is always a tension between validating input and fast execution time. In some cases, the ANSI spec requires such checks but in most cases it does not. In some case (like with some sequence functions), we have two versions, one safer and the other faster. But in many cases, no check is made.

It is true that silently processing erroneous input as if it were valid is an insidious type of error because the resulting erroneous result may not be noticed as erroneous until much later, or (if an error does eventually result) the cause of the error will be much harder to discover. But slow code is just as often useless in its own way. We have tried to strike a balance between safety and speed, but all users whould be aware that erroneous input may or may not be checked (with the bias toward not checked).

Users can do checks themselves. In the case, the following code will return T or NIL as the date string is or is not valid:

cl-user(48): (require :datetime)
cl-user(49): (defun valid-date-p (s)
               (string= s (format nil "~,v/locale-format-time/"
                                "%Y-%m-%d" 
                                (util.date-time:complete-date-time s))))
valid-date-p

cl-user(50): (valid-date-p "2011-02-28")
t
cl-user(51): (valid-date-p "2011-02-29")
nil
cl-user(52): (valid-date-p "2012-02-29")
t
cl-user(53):

2. Sometimes we add new or stricter argument checking so code which "worked" before now fails

Another user porting an application from an old verion of Allegro CL (5.0 or so) to 8.2 noted:

(setf mystring "hallo")
(subseq mystring 2 4)
"ll"

(subseq mystring 2 20) RETURNED "llo" in the old version

but in 8.2, signals this error:

Error: In SUBSEQ, `end' (40) is beyond the end of the sequence (5).
  [condition type: SIMPLE-ERROR]

The user asked if this changed was intentional and we replied: "Yes. We made the change to be more conformant with the standard and to help users find bugs in their code."

We mention this because we may add checks or fix bugs, particularly in a new release, without being explicit in the release notes about what we have done. Our tests suites generally test valid forms (unless we are checking error handling) so we not even be aware that invaid forms which previously "worked" (that is, returned satisfactory answers) no longer do. Patch descriptions often but not always have more information. However, user should be aware that changes which correct bugs in Allegro CL or bring Allegro CL into conformance with the ANS or with documented behavior may break code which was in fact erroneous but seemed to work before the patch or new release.

3. Getting an initialization message in the IDE Debug window

In the IDE, the main read-eval-print loop is displayed in a window called the Debug Window. This window is displayed after the IDE has started up. A user set several global variables in his .clinit.cl file and also had a format statement like (format t "Init file read~%") so he would know that the variables had been set. But he did not see the message in the Debug window.

The IDE is the Integrated Development Environment available with our Common Graphics window system. It is available on Windows, linux, and the Mac. The IDE is started after Allegro CL starts up, using the *restart-init-function* variable, whose value should be a list of functions or function objects which are called in order at the end of the Lisp startup sequence.

The user's system was in fact reading the init file but the value of *standard-output* at the time the file was read was the console window (which is commonly displayed only for an instant and then minimized as the IDE starts). So the message was unseen by the user.

We explained it is possible to have the message displayed in the Debug window, and indeed there were many ways to accomplish this, but no simple standard way. Further it cannot be easily done from the .clinit.cl file (which is the general Allegro CL init file) because that file is read well before the IDE is started so the Debug window does not yet exist and so there is no place to send the message directly. We did suggest some ways to accomplish what the user wanted.

The point of this entry is to make clear that startup sequences are often involved and certain tasks can only be accomplished once the sequence has progressed appropriately far (no message can be sent to the Debug window until that window has been created, for example). There are many hooks into the startup sequence (functions run, files loaded, variables examined, etc.) at many points in the sequence and which one should be used depends on exactly what you want to do (which is why there is no simple answer to the general question).

In this case, the answer was to use the startup.cl file in the Allegro directory, which is read near the end of the IDE startup sequence after the Debug window has been created and when it is the value of *standard-output*. But other tasks may require other solutions. The startup sequence for Allegro CL is described in startup.htm That for the IDE is described in cgide.htm. If you have trouble with initializations, please ask Franz customer support at support@franz.com (as we have a lot of experience). While getting initializations right can be complicated, once they are set up correctly they usually work fine from then on.

4. Single-float math has only 7 or so digits are accuracy

Issues similar to this one come up regularly. A user of Allegro CL on a 64-bit machine gets:

(truncate 100001111.00)
100001112
0.0
(floor 100001111.00) 
100001112 
0.0

Those results do not look right, but we found the value of *read-deafult-float-format* was its initial value (single-float) and single-floats are 32-bit values even in a 64-bit Lisp. Single-floats have 24 bits for the mantissa (along with 8 for the exponent and 1 for the sign -- yes that adds to 33 bits but the high bit of the mantissa is always 1 and so is not stored). 24 binary bits can represent integers from 0 to (1- 16777216), so only a maximum of 8 decimal digits can be represented. The numbers in the example sent by the user have 9 digits and differ only in the ninth digit. In fact, the values 100001111.00 and 100001112.00 are represented by the same single float:

cl-user(178): (= 100001111.00 100001112.00)
t 

Once you know this, the initial results are less suprising. If extra digits of accuracy are important, you should use double-floats.

5. Downloading patches often requires that images be rebuilt

A number of user downloaded patches (with the Download Patches dialog in the IDE or with sys:update-allegro) are were surprised when exiting images would not start. It is often the case that changes require that existing images be rebuilt because of the patches. Users are told that rebuilds, which are done with the update program, called update.sh on Unix platforms and update.exe (and also on the Start menu) on Windows. In rare instances, the update program will itself fail. When this happens, it is usually because one of the images never worked because of a library mismatch (usually the IDE image allegro.dxl on platforms where the GTK (a windowing utility library) installation is not correct for the IDE) but was never tried before trying to update. Failures of the update program are best handled by contacting Franz customer support at support@franz.com.

Copyright © 2023 Franz Inc., All Rights Reserved | Privacy Statement Twitter