[Openmcl-devel] peek-char, interpretation of first argumenthttp://www.nbcolympics.com/video?ocid=Yahoo

Pascal J. Bourguignon pjb at informatimago.com
Thu Feb 20 11:30:24 PST 2014


Erik Pearson <erik at adaptations.com> writes:

> Never one to not jump to my own defense or fail to flog a dead
> equine, and almost always finding that this is a mistake, I
> nevertheless venture one last flail. When researching the etymology
> of the construction "if peek-char is not supplied or nil", I find in
> the MacLisp manual the precedent for this "variable arity
> polymorphism based on type" in the definition of "read":
>
> (READ [file] [eofval])
>
> If only one argument is given, it may be either stream or eofval. If
> it is a file, an sfa, or NIL, it will be assumed to be stream;
> otherwise, it will be taken as eofval.
>
> If file is not supplied or is NIL, the default input stream as
> controlled by the variables ^Q, INFILE, and TYI will be used.
>
> Interesting, perhaps, to an infinitiesimal sliver of humanity.


However, this kind of function signature cannot be specified with CL
lambda lists, that is, the parsing of the arguments for those functions
cannot be performed by cl:defun.

You would have to write something like:


    (defun maclisp:read (&rest arguments)
      (let ((file   (maclisp::internal-select-stream maclisp:^q maclisp:infile maclisp:tyi))
            (eofvar nil))
       (case (length arguments)
        ((0))
        ((1)  (typecase (first arguments)
                 (stream (setf file   (first arguments)))
                 (t      (setf eofval (first arguments)))))
        ((2)  (setf file   (first arguments))
              (setf eofval (second arguments)))
        (otherwise (error "Too many arguments")))
      (maclisp::internal-read file eofvar)))


Now, one could write an extended defun macro that would take a lambda
list specification that would include the types and default values of
the arguments and expand to something similar to the above.  For
example:

    (extended:defun maclisp:read (&typed-optional
                                  (file   stream (maclisp::internal-select-stream
                                                  maclisp:^q maclisp:infile
                                                  maclisp:tyi))
                                  (eofvar boolean nil))
      (maclisp::internal-read file eofvar))    


This wouldn't be too difficult.  However, it would have dire
consequences to the Common Lisp programming style, because it would
require much more control on the type of the arguments of functions,
ie. on the type of all the values in the program.


For example, if you write:

    (cl:defun example:read (&optional
                              (file (maclisp::internal-select-stream
                                     maclisp:^q maclisp:infile
                                     maclisp:tyi))
                              (eofvar nil))
      (example::internal-read file eofvar))    

you can pass to example:read any value, even not a strem, to the file
parameter.  There's nothing in example:read that really requires file to
be a stream, since file is only used as a parameter to
example::internal-read, the typing of file is defered to this function.
In effect, what we have here is a generic function (in the general
sense, not that of CL generic-function), not a function restricted to
stream types.  In practice in CL, it's used to let one pass T or NIL, or
a string with a fill-pointer,   instead of a stream to such functions as
FORMAT, with a meaning assigned to those values.  

    (let ((out (make-array 100 :adjustable t :fill-pointer 0
                               :element-type 'character)))
      (format out "Hello ~A" 'world)
      out)
    --> "Hello world"

This wouldn't be possible anymore if FORMAT was defined with
&typed-optional arguments.

In the worst case, they would define a FORMAT-DESTINATION type to wrap
the various cases:

    (format (make-instance 'format-specification :string-target out)
            "Hello ~A" 'world)

    (format (make-instance 'format-specification :stream *query-io*)
            "Hello ~A" 'world)

    (format (make-instance 'format-specification :string-result t)
            "Hello ~A" 'world)

    (format (make-instance 'format-specification :symbolic-stream t)
            "Hello ~A" 'world)

just to be able to write also:

    (format "Hello ~A" 'world)

!

Go down this slope, and you end up with Java!


-- 
__Pascal Bourguignon__
http://www.informatimago.com/
"Le mercure monte ?  C'est le moment d'acheter !"




More information about the Openmcl-devel mailing list