Recent support questions of general interest

Documenting a large and complicated product like Allegro CL is never easy and even conscientious users often have difficulty finding answers to specific questions in the documentation. In this note, we flag some recent support questions which might be of general interest. They are all from 2012.

How do I get rid of #'s in trace or debug output?

One reason #'s can appear is the governing print level is too small for the depth of a list, as shown in the following (rather contrived) example:

cl-user(14): (defun foo () nil)
foo
cl-user(15): (foo '(x (y (z (a (b (c)))))))
Error: foo got 1 arg, wanted 0 args.
[1c] cl-user(16): :zoom
Evaluation stack:

   (cerror "Ignore the extra args." program-error ...)
 ->(foo (x #))
   (eval (foo '#))

In the zoom debugging output, we see the call to foo as (foo (x #))(foo '(x (y (z (a (b (c))))))). This is because the print level in debugging output is controlled by the valriable tpl:*zoom-print-level*, whose initial value is 3. If you set that variable to nil, you can see the whole form.

Similarly, you may see in trace output:

 1[2]: returned
           #4=((COMMON-LISP-USER::V1671344
                (#8=(:AMBIGUOUS-MOD COMMON-LISP-USER::V1671344 :TRUE) ...

That indicates the governing print circle control is true (and the #4 and $8 can appear elsewhere as abbreviations). The relevant variable here is excl:*trace-print-circle* (which was true when the output displayed was printed.

Allegro CL has a number of print control variables which control different aspects of printing. The standard Common Lisp variables (like cl:*print-level*) only control output of Common Lisp print functions. In contrast, tpl:*print-level* and friends control what is printed when a form is evaluated at a Lisp prompt. Here are all the varieties of print level (with the initial values shown):

cl:*print-level*       value: nil
excl:*trace-print-level* value: 5
excl:*step-print-level*  value: 4
tpl:*zoom-print-level* value: 3
tpl:*print-level*   value: 5

Other printer control valiables (print length, print circle, etc.) also have top-level, zoom, step, and trace varieties.

How can RETURN be a special operator? It is not in the list of special operators in the ANSI standard.

The user who asked this question was referring to the list of special operators found here. But elsewhere (here) the ANSI standard says "An implementation is free to implement any macro operator as a special operator, but only if an equivalent definition of the macro is also provided." in Allegro CL we have:

  user(30): (special-operator-p 'return)
   #<special operator RETURN @ #x1000054c32>
  user(31): (macro-function 'return)
  #<Function macroexpand-1-transform>

So return is defined (as required) both as a special operator and a macro. Because it is a special operator, the compiler can handle it more efficiently. Note that user code cannot create special operators.

The user who asked the question was using a code walker that tested for a symbol naming a special operator before testing whether it named a macro, and was thus getting confused.

I want my own version of OPEN to be used by WITH-OPEN-FILE. Can I do that?

The user wanted his macro to expand to this (approximately):

   (flet ((open (s &rest initargs)
	    (when s (apply #'open s initargs))))
     (with-open-file (var filename)
       ...))

Then if the filename was NIL, NIL was returned. Our response was he should not do this. The ANSI standard forbids it (see here), and the danger is that even though it might work in the current version and patch level (as the macro seemed to), changes we might make between versions on even in a patch might cause things to break in a way that would make debugging difficult.

I accidentally defined a function with a keyword argument repeated, but got no warning or error, and strange behavior.

Here is a transcript:

USER: (defun foo (&key (bar t) (bar t)) (print `(bar ,bar)))
FOO
USER: (foo)

(BAR T) 
(BAR T)
USER: (foo :bar nil)

(BAR NIL) 
(BAR NIL)
USER: (compile 'foo)

; While compiling FOO:
Warning: Variable BAR is never used.
FOO
T
NIL
USER: (foo :bar nil)

(BAR T) 
(BAR T)

There is a bug here (note that the compiled and interpreted results are different) but aside from that, it is not clear that double argument is incorrect (probably because the writers of the ANSI standard did not consider the case, not that they thought it was desirable). However, we have an enhancement request to issue a style warning.

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