PEP? context overloading: if wants(type): ...

Alex Martelli aleaxit at yahoo.com
Mon Aug 6 10:22:55 EDT 2001


"Jim Dennis" <jimd at vega.starshine.org> wrote in message
news:9klgl0$1frt$1 at news.idiom.com...
> I'm not qualified to formally champion a PEP, but I'd
>  like to raise the question here to see if it's of interest.
>
>  One feature that I find interesting about PERL is it's
>  "context sensitivity."

I can accept this, in the context of the (mythical, I
think) Chinese curse "may you live in interesting times".

> (By contrast the inability to overload
>  a function on *return* type is a limitation of C++ that I find
>  irritating and unnecessary).

You are, indeed, consistent: this IS one of the few places
where C++ did not choose to go for all-out complexity but
retain a minimum of sanity instead (have you ever programmed
in Algol-68, where no such limitation existed...?).


>  I'd propose, if I felt qualified to do so, to offer a "wants()"
>  or builtin that would allow a method to determine the desired
>  return type or "context" of an invocation.
>
>  So the use could look like:
>
> import types
>   if wants(IntType):
> return n
> elif wants(TupleType):
> return (n1,n2)
> elif wants(StringType):
> return `n`
> elif wants(VoidType): # NoneType?
> return
>
>  What am I missing about this?  What would it hurt?

If it were possible at all within Python, it would hurt the heads
 of poor guys and gals trying to understand what IS going to
happen on a given call.  Consider a typical 'skeleton'/toy/
simplified case:

def receiver(something):
    print 'receiver starts'
    if isinstance(something, IntType):
        print 'got an int',something
    elif isinstance(something, StringType):
        print 'got a string',something
    else:
        print 'got something funny',type(something),something

def sender():
    print 'sender starts'
    if wants(IntType):
        print 'sending an int'
        return 23
    elif wants(StringType):
        print 'sending a string'
        return 'vingt-trois'
    else:
        print 'sending junk'
        return None

receiver(sender())

...now what?  What is SUPPOSED to happen -- a compile-time
error (fat chance:-), run-time error (at what point in time?),
or what?  How IS Python supposed to determine what kind of
thing receiver wants -- using the time machine to see what
typetests (isinstance, here) receiver is going to perform?  And
what if we had:
    whatever = sender()
    receiver(whatever)
...?  'whatever' obviously doesn't "want" anything at all -- it's
perfectly willing and able to become a reference to anything
at all.  So what now?

All in all, my personal opinion on this idea is that it's luckily
impossible to implement in Python for dearth of 'strong'
enough "contexts" -- contexts that want to have something
to say about what's passed to them.  Just about the only
'strongish' one is unpacking-assignment:
    a,b,c,d = floop()
where it IS a runtime error if floop returns anything except
a sequence of length 4 (and the compiler can determine
this) -- still doesn't care whether it's a string, list, tuple,
or other kind of sequence, but does care about sequencehood
and exact length.  If one had a global function answering the
question "am I called in a context where a sequence of a
specific length is required, and if so what length is that" I
guess it _might_ have some marginal use.  Implementation
would require a lookahead in the bytecode stream to see if
the very next relevant opcode after the currently-executing
CALL_FUNCTION n is, or isn't, an UNPACK_SEQUENCE k --
nothing _too_ terrible I guess -- one could prototype it in
Python without breaking a sweat -- frm=sys._getframe(2),
with frm.f_lasti+3 being the index in the bytecode of code
object frm.f_code of the next opcode to be executed after
the caller of want() returns.

But it would probably still be best if it only worked in the
simplest case, with no 'lookahead' needed -- e.g., NOT for:

def f(x):
    a,b,c=x

or equivalently:

x=whatever()
a,b,c=x

The kind of black magic needed to determine from inside
whatever() that its return value is *eventually* going to
be subjected to unpacking would be a disaster.


Alex






More information about the Python-list mailing list