Adaptation and typecasting (was Re: [Python-Dev] replacing 'global')

Phillip J. Eby pje at
Tue Oct 28 18:33:19 EST 2003

At 10:03 AM 10/29/03 +1100, Delaney, Timothy C (Timothy) wrote:
> > From: Phillip J. Eby [mailto:pje at]
> >
> > At 09:56 AM 10/28/03 +0100, Alex Martelli wrote:
> > >AND, adaptation is not typecasting:
> > >e.g y=adapt("23", int) should NOT succeed.
> >
> > And, why do you consider adaptation *not* to be typecasting?
> > I always
> > think of it as "give me X, rendered as a Y", which certainly
> > sounds like a
> > description of typecasting to me.
>Because (IMO anyway) adaption is *not* "give me X, rendered as Y". 
>Adaption is "here is an X, can it be used as a Y?".
>They are two distinct concepts, although obviously there are crossover 

Yes, just like 2+2==4 and 2*2==4.

>A string cannot be used as an int, although an int can be created from the 
>string representation of an int.

I'd often like to "use a string as an integer", or use some arbitrary 
object as an integer.  Of course, there's a perfectly valid way to express 
this now (i.e. 'int()'), and I think that's fine and in my code I will 
personally prefer to use int() to mean I want an int, because that's clearer.

But, if for some reason I have code that is referencing some protocol as a 
*parameter*, say 'p', and I have no way to know in advance that p==int, 
then the most sensible thing to do is 'adapt(x,p)', rather than 
'p(x)'.  (Assuming 'p' is expected to be a protocol, rather than a 
conversion function.)

Now, given that 'p' *might* be 'int' in some cases, it seems reasonable to 
me that adapt("23",p) should return 23 in such a case.  Since 23 satisfies 
the desired contract (int) on behalf of "23", this seems to be a correct 
adaptation.  For a protocol p that has immutability as part of its 
contract, adapt(x,p) is well within its rights to return an object that is 
a "copy" of x in some sense.  The immutability requirement means that the 
"adapted" value can never change, so really it's a *requirement* that the 
"adaptation" be a snapshot.

>Adaption should not involve any change to the underlying data - mutating 
>operations on the adapted object should (attempt to) mutate the original 
>object (assuming the adapted object and original object are not one and 
>the same).

I agree 100% -- for a protocol whose contract doesn't require immutability, 
the way 'int' does.

I think now that I understand, however, why you and Alex think I'm saying 
something different than I've been saying.  To both of you, "typecasting" 
means "convert to a different type" at an *implementation* level (as it is 
in other languages), and I mean at a *logical* level.  Thus, to me, "I 
would like to use X as a Y" includes whatever contracts Y supplies *as 
applied to X*.  Not, "give me an instance of Y that's a copy of X".

It just so happens, however, that for a protocol whose contract includes 
immutability, these two concepts overlap, just as multiplication and 
addition overlap for the case of 2+2==2*2.  So, IMO, for immutable types 
such as tuple, str, int, and float, I believe that it's reasonable for 
adapt(x,p)==p(x) iff x is not an instance of p already, and does not have a 
__conform__ method that overrides this interpretation.

That such a default interpretation is redundant with p(x), I also 
agree.  However, for code that uses protocols dynamically, that redundancy 
would eliminate the need to make a dummy protocol (e.g. 'IInteger') to use 
in place of 'int'.

OTOH, if Guido decides that Python's eventual interface objects shouldn't 
be types, then there will be an IInteger anyway, and the point becomes moot.

Anyway, I can only understand Alex's objection to such adaptation if he is 
saying that there is no such thing as adapting to an immutable 
protocol!  In that case, there could never exist such a thing as IInteger, 
because you could never adapt anything to it that wasn't already an 
IInteger.  Somehow, this seems wrong to me.

More information about the Python-Dev mailing list