I've been unable to deduce a type syntax that would allow me to do this.
An example of the code would be:
(defun foo (x)
(declare (type list x))
(dolist (item x)
(print (elt item 0)) ))
I know that I could add more type info further downstream. E.g. I could
declare that "item" is a string type. But sometimes this is inconvenient,
or it may be difficult for me to do the type inference myself in convoluted
code. Is there any type specifier I could use in the original declaration of
the variable "x" that would mean "a list of strings"?
`elt' is the most general of all the sequence accessors, so if you are
inclined to declare "item" of type string or "x" of type list of strings,
you're probably much better off using a more specific accessor, such as
`char' or `schar'.
to me, `elt' communicates "this function needs to deal with sequences of
unknown type", and that would be contradicted by a declaration of the type
of the sequence such as with (declare (string item)).
on the other hand, one of the few annoying things about Common Lisp is that
the effect of declarations is so hard to predict, both in portable code and
in particular implementations. often, the code is exactly the same unless
(declaim (optimize (speed 3) (safety 0) (debug 0))) is in effect when
compiling highly declared code. since declarations are mainly optimization
tools in Common Lisp, you may find it instructive to profile the code, use
the most type-specific functions to your data, and review the algorithm for
inherent time- and space-related costs before you start introducing strong
type declarations, since they introduce a rigidity that makes the code much
harder to maintain, develop and reason about, not to mention that people
who read code with lots of declarations will overlook performance problems
in the algorithm -- just like C/C++ programmers tend to optimize the hell
out of inherently slow algorithms. optimization is perhaps the single most
counter-intuitive of all the complex tasks programmers have to deal with.
like everything else, I guess the "easy answers" attract people, but don't
succumb to the siren songs of trivial optimizations -- they make the more
important optimizations much harder to locate.
404 Give me a URL I cannot refuse.
> I've got a variable whose value will be a list of particular items, say
> strings. I'd like to specify its type precisely, so that a clever compiler
> could do type inference about the components.
> I've been unable to deduce a type syntax that would allow me to do this.
> Any suggestions?
> An example of the code would be:
> (defun foo (x)
> (declare (type list x))
> (dolist (item x)
> (print (elt item 0)) ))
> I know that I could add more type info further downstream. E.g. I could
> declare that "item" is a string type. But sometimes this is inconvenient,
> or it may be difficult for me to do the type inference myself in convoluted
> code. Is there any type specifier I could use in the original declaration of
> the variable "x" that would mean "a list of strings"?
No. There is no *valid* type specifier that you can specify as
(declare (type (list string) x))
and that your compiler would be allowed to act on. It will probably compile
but ignore the declaration. The only way to do this kind of thing in Common
Lisp is the C++ way of defining your own cons type. For example
(defstruct mycons cdr (value :type string))
Of course then you would have the same classic C++ problem of having to
define your own bloat set of generics, ie. car, cdr, rplaca, rplacd ... etc.
William P. Vrotney - vro...@netcom.com
I certainly agree with the methodology of choosing good algorithms before
trying to super-optimize type declarations.
But I disagree that strong type declarations introduce unwanted rigidity.
As a programmer, I usually have in mind particular types for the arguments
of a function I'm writing. And I write the code with those assumptions in
mind, e.g. with type-specific calls deep within my function.
I find that getting in the practice of adding declarations is as much
documentation as anything else. It's nice to have the assumptions laid out
explicitly at the top of the code, rather than having to search through the
details of the code, and then trying to derive the types based on the
type-specific function calls that are made.
Since I've already made the mental assumption that the arguments are of a
particular type, I might as well tell the compiler about it. If that
assumption is violated, I'll probably have to fix lots more than just the
declarations. (E.g. the type-specific function calls will fail too.)
Besides this benefit of programmer documentation, since the types are
machine-understandable as well, I occasionally get lucky with compiler
optimizations. This seems to be a win-win situation to me.