[Ecls-list] *features* and CDR

Pascal J. Bourguignon pjb at informatimago.com
Fri Aug 19 10:45:56 UTC 2011

Juan Jose Garcia-Ripoll <juanjose.garciaripoll at googlemail.com> writes:

> I have been reading the CDR documents and none of them seems to
> mandate the inclusion of some feature to signal the presence of a CDR
> in an implementation. *features* right now is quite populated and I
> would not want to fill it with further names that may collide with
> other users's. Does anybody have a strong opinion or is better
> informed than me in this respect?

The presence of some features need to be determined at read-time.  

Even for features that can be determined at run-time, you would have to
use a variable or a function, the presencce of which will have to be
determined at read-time.

So it seems to me that we need a keyword on *features*.

Basically, you have the choice between:

    (when (and (find-package "CDRn")
               (find-symbol "FN" "CDRn")
               (fboundp (find-symbol "FN" "CDRn")))
       (funcall (find-symbol "FN" "CDRn")))


    #+CDRn (cdrn:fn)

Now, we could define a CDR that would allow us to determine at run-time,
if a specific CDR is implemented.  Something like:

   (cdr:max-implemented-cdr-number) --> integer
   (cdr:implementedp n) --> boolean

Which would allow us to write things like:

   (dotimes (i (1+ (cdr:max-implemented-cdr-number)))   
     (when (cdr:implementedp i)
        (format t "~A implements CDR~D~%" 
                   (lisp-implementation-type) i)))

but as you can see, we need a *feature*

   (dotimes (i (1+ (cdr:max-implemented-cdr-number)))   
     (when (cdr:implementedp i)
        (format t "~A implements CDR~D~%" 
                   (lisp-implementation-type) i)))
   #-cdr (format t "~A implements no CDR~%"

So the minimum number of keyword on *features* that would be required is
one, but for that we would have to define an additionnal CDR as above.

Now, for CDRs that don't involve new symbols, eg. CDR7, you can just

  (defun cl-user::fmt (stream argument colonp atsignp &rest params)
    (declare (ignore stream argument colonp atsignp))
    (format t "~S" params))

  (format t "~/fmt/ and ~:*~,/fmt/ ~:[may be different~;should be the same~].~%"
            nil #+cdr (cdr:implementedp 7) #-cdr nil)

but again, it might be easier to write:

  (format t  "~/fmt/ and ~:*~,/fmt/ ~:[may be different~;should be the same~].~%"
             nil (member :cdr7 *features*))

or just:

   #+cdr7 (format t "cdr7 implemented~%")
   #-cdr7 (format t "cdr7 not implemented~%")

It seems to me that the CDRs of the kind of CDR7 will be much rarer, and
in either case, the convenience of *features* and read-time
conditionnalisation is overwhelming.   

Even if we can always write things like:

   #+#.(cl:if (cl:and (cl:find-package "CDR")
                      (cl:find-symbol "IMPLEMENTEDP" "CDR")
                      (cl:fboundp (cl:find-symbol "IMPLEMENTEDP" "CDR"))
                      (cl:funcall (cl:find-symbol "IMPLEMENTEDP" "CDR") 7))
           '(:or)) (format t "cdr7 implemented~%")

it is clear that what's really wanted, is a keyword on *features* for
each CDR.

Finally, I would like to add a note to CDR writers.  The purpose of the
CDR proccess is to improve or evolve the standardization of Common Lisp,
by adding missing features, or precising existing features (eg. CDR9).
In this spirit, I would suggest that CDRs should not specify
implementation dependent behavior.  For example, CDR9 says:

    The API to the requested functionality can be as simple as providing
    a function called make-variable-file-local in whatever extension
    package a Common Lisp implementation happens to use [...].

This is very bad, because this will force us to write code such as:

    #+(and cdr9 clisp) (ext:make-variable-file-local '*my-var*)
    #+(and cdr9 ccl)   (ccl:make-variable-file-local '*my-var*)
    #+(and cdr9 sbcl)  (sb-ext:make-variable-file-local '*my-var*)
    #+(and cdr9 (not (or clisp ccl sbcl))) (error "CDR9 is implemented, but ~
                                                   I don't know where it is!")
    #-cdr9 (error "CDR9 is not implemented")

which is shameful and a bore.  Clearly, this kind of CDR are no gain,
and we would be better without.

On the other hand, if the CDRs specify new symbols, they should always
specify CDNn as a package name (or nickname) where these symbols must be
exported from.   I think that even if another package name is specified,
a CDRn nickname should also be specified, to allow for different
versions to be present (the implementation may able to provide several
versions in a single package, with several CDRn nicknames, or as
different packages).

So given such a correction to CDR9:

    The API to the requested functionality must be implemented by providing
    a function called cdr9:make-variable-file-local.

we could write:

   #+cdr9 (cdr9:make-variable-file-local '*my-var*)
   #-cdr9 (error "CDR9 is not implemented")

__Pascal Bourguignon__                     http://www.informatimago.com/
A bad day in () is better than a good day in {}.

More information about the ecl-devel mailing list