On Tue, Nov 18, 2003 at 10:11:08AM +0100, Nicolas Neuss wrote:
> Henrik Motakef <usenet-reply@...> writes:
> > Is it possible and/or meaningfull to declare the ftype of a generic
> > function? It looks like in sbcl (0.8.5), a form like
> > (defgeneric foo (x y))
> > automatically implies a declaration like
> > (ftype (function (t t) *) foo)
> > overriding any previous explicit declaration, and issuing a style
> > warning about it if they don't match (which they usually don't). Is
> > there a way to declare a more strict type for a gf, so that ideally I
> > would get neat warning for methods that obviously don't conform to it
> > like I would get for ordinary functions?
It does seem as though it should be meaningful to make such narrower
declarations. Such declarations be useful not only for the
compile-time error checking you describe, but also for efficiency
reasons. E.g., when you declare that a method always returns a
SIMPLE-VECTOR, any sequence function (like FIND, SOME, or CONCATENATE)
on the return value could be compiled efficiently.
I think -- unless I'm getting confused about ANSI FTYPE semantics
again, which is entirely possible -- that ideally successive FTYPE
declarations should combine to the intersection of the declared types,
so that e.g.
(DECLAIM (FTYPE (FUNCTION (REAL REAL) *) FOO))
(DECLAIM (FTYPE (FUNCTION (REAL T) INTEGER) FOO))
would mean something like
(DECLAIM (FTYPE (FUNCTION (REAL REAL) INTEGER) FOO))
But even if that is theoretically the right thing to do, I'm not sure
whether the type inference logic in SB-KERNEL is smart enough to make
it easy to implement this.
Meanwhile, there is a point to issuing a declaration like
(ftype (function (t t) *) foo)
at the point of
(defgeneric foo (x y))
It can avoids some kinds of problems (suppressing undefined function
warnings, while allowing some errors like incorrect numbers of
arguments to be caught at compile time). Unfortunately, yes, the
effect of overwriting more precise definitions of FTYPE FOO elsewhere
seems pretty unfortunate.
> I think for gfs a combination of types would be the most reasonable type
> declaration, e.g. (or (function (string) fixnum) (function (list) fixnum)).
> To be practically usable, this should probably adapt dynamically to new
> method definitions...
If you are suggesting keeping the FTYPE definition as narrow as
the OR of all DEFMETHODs seen so far, I don't think that's going
to work correctly.
(DEFGENERIC FOO (X))
(DEFMETHOD FOO ((X INTEGER)) ...)
;; so here FTYPE FOO would be (OR (FUNCTION (INTEGER) *))?
(DEFUN FROB (X)
(INTEGER (FOO X))
(REAL (LIST (FOO X) (EST-PRECISION X))) ;should not compile to type error
(DEFMETHOD FOO ((X SINGLE-FLOAT)) ...)
(DEFMETHOD FOO ((X DOUBLE-FLOAT)) ...)
;; Now FTYPE FOO has become
;; (OR (FUNCTION (INTEGER) *)
;; (FUNCTION (SINGLE-FLOAT) *)
;; (FUNCTION (DOUBLE-FLOAT) *))
;; but it's too late to avoid compile-time errors in DEFUN FROB.
William Harold Newman <william.newman@...>
We were bedevilled by the daemons of diagrammatic overdesign. My God,
three little boxes drawn on the back of a napkin, Game, Frame, and
Throw, and it was still too complicated and just plain wrong.
-- Robert C. Martin, _Agile Software Development_, p. 72
PGP key fingerprint 85 CE 1C BA 79 8D 51 8C B9 25 FB EE E0 C3 E5 7C