Python from Wise Guy's Viewpoint

Pascal Costanza costanza at web.de
Tue Oct 28 09:38:28 EST 2003


Andreas Rossberg wrote:
> Pascal Costanza wrote:
> 
>>
>>> As an example of the kind of "overloading" (or type dispatch, if you 
>>> want)
>>> you cannot express in dynamically typed lagnuages: in Haskell, you can
>>> naturally define functions which are overloaded on their return type, 
>>> i.e.
>>> you don't need any value at all at runtime to do the "dispatch". For
>>> example, consider an overloaded function fromString, that produces 
>>> values of
>>> potentially arbitrary types from strings.
>>
>>
>> Wrong.
> 
> 
> Not sure how the "wrong" relates to the quoted paragraph, but I guess 
> you mean my conjecture that you cannot dispatch on return types with 
> dynamic typing.
> 
>> (defmethod from-string-expansion (to-type string)
>>   (if (or (subtypep to-type 'sequence)
>>           (subtypep to-type 'character)
>>           (eq to-type t))
>>     `(coerce ,string ',to-type)
>>     `(coerce (read-from-string ,string) ',to-type)))
>>
>> (defmacro set-from-string (x string &environment env)
>>   (multiple-value-bind
>>     (bound localp declarations)
>>     (variable-information x env)
>>     (declare (ignore bound localp))
>>     (let ((type (or (cdr (assoc 'type declarations)) t)))
>>       `(setf ,x ,(from-string-expansion type string)))))
> 
> 
> Interesting example, thanks for showing it. I'm not fluent enough in 
> Lisp to understand how this actually works but it does not seem to be 
> extensible in a compositional way (you have to insert all type cases by 
> hand).

No, at least not in the default method for from-string-expansion I have 
shown above. That method only covers the default cases, and needs to 
distinguish different ways how Common Lisp handles pre-defined types.

What you would need to do for your own types is to write your own 
specialized versions of from-string-expansion:

(defmethod from-string-expansion ((to-type (eql 'foo)) string)
   `(somehow-convert-string-to-foo ,string))

You don't need to modify the method given above. (You need to write 
conversion routines for your own types in any language.)

> And does the resolution work transitively? I.e. if I write some 
> complex function f using fromString somewhere, performing arbitrary 
> calculations on its return value of type t, and returning something of a 
> type containing t, is all this code parametric in t such that I can call 
> f expecting arbitrary result types? All this would be automatic in Haskell.

It should be possible in principle. The macro shown above is expanded at 
compile-time (this is 100% correct, but sufficiently correct for the 
sake of our discussion). The &environment keyword captures the lexical 
environment that is current at macro expansion time. 
VARIABLE-INFORMATION looks up type information about a variable in that 
environment, before the code is actually translated into its final form.

The original idea for such environment objects was that you could not 
only look up standardized information about entities of the compilation 
environment, but that you can also stuff in your own information. So in 
principle, it should be possible to use this as a basis for a type 
inferencing mechanism.

The downside of all this is that ANSI Common Lisp doesn't define the 
needed functions to do all this. It defines such environment objects 
only in very rudimentary ways that are actually not powerful enough. 
CLtL2 had this stuff, but apparently it had some glitches that are hard 
to get right, and it was decided to leave this stuff out of the ANSI 
standard.

There are Common Lisp implementations that implement this functionality 
to a certain degree, and apparently Duane Rettig of Franz Inc. is 
currently working on an implementation that has sorted out the edge 
cases. They seem to consider making this available as open source.

It's probably possible to do similar things with the ANSI-defined 
DEFINE-COMPILER-MACRO, or with proprietary extensions like DEFTRANSFORM 
in LispWorks.

> Also note that your transcript shows that your approach indeed requires 
> *explicit* type annotations, while you would rarely need them when doing 
> the same thing in a language like Haskell.

I think it should be possible in principle to add type inferencing to 
Common Lisp as a sophisticated macro package, even without proper 
environment objects.

It would probably take serious effort to implement such a beast, and it 
would be difficult to solve interferences with "third-party" Lisp code, 
but at least you would not need to change the base compiler to add this.

> Anyway, your code is complicated enough to make my point that the static 
> type system gives you similar expressiveness with less fuss.

Yes, you're right. If you would want/need static type checking by 
default, it wouldn't make much sense to do this in a dynamically typed 
language that treats static type checking as an exceptional case. And 
vice versa.


Pascal

-- 
Pascal Costanza               University of Bonn
mailto:costanza at web.de        Institute of Computer Science III
http://www.pascalcostanza.de  Römerstr. 164, D-53117 Bonn (Germany)





More information about the Python-list mailing list