I agree about time-frame being a danger. "Always scale up, not down." So
might do a solution based on our own, custom __cgetitem__ first, and
then try to generalize *that* afterwards if there's time. (But I'll
still prototype __getitem__ just to see).
The only problem is that __cgetitem__ requires conventional overloading,
which I was *not* currently planning on doing; I intended this to be a
more Pythonic alternative ("don't introduce features that's not in
Python "just because we can" -- compile time duck typing is really just
Python behaviour at compile-time, normal overloading means a control
flow that cannot be had in Python).
Robert Bradshaw wrote:
> On May 24, 2008, at 1:03 PM, Dag Sverre Seljebotn wrote:
>
>> Instantiation (1) of the function is symmetric to this, raising an
>> exception if control reaches the place where the integer is returned.
>>
>> So the end result is that the "int-return-type" instantiation of
>> get_something returns the proper, native C int when called with
>> as_str=False, and raises a coercion exception when called with
>> as_str=True.
>>
>> [1] Even if this may seem hard to wrap ones head around, the end of
>> the
>> story for the end-user is rather pleasing; one gets more or less the
>> same behaviour as if get_something was declared with an "object"
>> return
>> type. It should natural to use. But no object coercion is involved for
>> the compiler, so speed is maintained.
>
> Interesting idea, I think Haskell has something like this. It's like
> type coercion going the opposite direction--one wants an int result
> so it changes the expression itself (perhaps after passing through
> several layers? How feasible is this?). I'd rather be a bit more
> explicit (especially for ease of doing type inference for statements
> like "x = arr[5]").
There's not any "magic" or unfeasability involved as far as I can see.
Full algorithm:
- When calling a function with one or more generic types (possibly
return type!), look it up in an instantiation dict.
- If the dict lookup misses, instantiate the function like this: a)
mangle name, b) insert the exact types that were used in the call (void
for return type if it is discarded), c) the body is copied literally,
except for return statements which are changed according to (*).
- If the copied body contains calls to functions with generic types,
recurse.
(*) If the return type is not "generic", return statements are handled
like normal. If the return type is "generic", any return statements:
- When the (actual, instantiated) return type ended up being void,
evaluate expression but discard result (as the caller obviously discards
the result). In this case, returning multiple different types will just
work.
- When the actual, instantiated return type is T != void, then treat
return statements like normal (i.e. if returning from a function with
return type T), except for the cases where coercion fails, in which
case, rather than giving a compile-time error, one evaluates expression,
discards result, and inserts instructions to raise runtime exception.
> Essentially, what you really want is __getitem__ to return a variety
> of types, determined at compile time, and without coercion through an
> object. For inlined functions perhaps we could have a phase
> automatically optimizing away <type><object>x where there is a direct
> conversion from x to type (if the <object> wasn't explicitly
> requested by the user).
That's what I was hoping to avoid by doing something *simpler*. As long
as <object> coercion is not a perfect round-trip this can have
unintended side-effects etc. etc. that I'd have to sort out, and the
above seems much simpler and more elegant (to me).
--
Dag Sverre
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev