Robert Bradshaw wrote:
> On Apr 24, 2009, at 1:24 AM, Dag Sverre Seljebotn wrote:
>> So in the example
>>
>> Point& operator[](int edge);
>>
>> if you wanted to print something when changing a point, you could do
>>
>> PointInPolygon operator[](int edge);
>>
>> instead, and PointInPolygon would contain both a reference to the
>> Polygon
>> and the index of the edge, and have overloaded "operator=" and
>> "operator
>> Point" which would work as setitem and getitem, respecticely.
>>
>> So what I'm saying is: Mapping C++ operators to Python operators
>> and vice
>> versa is difficult, with possibly many special cases where e.g. a
>> Python
>> setitem operator would map to an entire C++ expression involving many
>> operators.
>>
>> Starting out with the binary operators only is simpler and probably
>> a good
>> idea :-)
>
> Perhaps I'm taking a too simplistic view of things, but it seems that
> all we have to do is figure out whether or not we can pass a given
> operator onto the C++ code, which is much easier to reason about.
> Also, because in Python assignment is not an expression, we don't
> have to worry about its return value.
Hmm. That's a nice perspective to have; but I don't think it is
"obvious" and leads to some fairly concrete consequences IMO: Operators
must be declared using the Python operator syntax. So you are never
declaring anything about "operator[]" in Cython, instead you are
declaring "what types are allowed for the full statement 'x[i] = y'".
(If we start using C++ syntax but don't support the whole thing in the
same way it will bring lots of confusion I think.)
This pushes the hard work over to writing of the C++ pxd wrapper
(whether that's a person or in time an automatic script). I think that's
a good idea. It also makes Cython's grammar simpler than the alternative.
However, a consequence is that if we support overloading, we must also
support overloading solely on return values :-) See below.
Some examples:
int operator[](int idx)
would give
int __getitem__(int idx)
while
int& operator[](int idx)
would be declared as
int __getitem__(int idx)
void __setitem__(int idx, int value)
A more complicated example, with a collection which can retrieve items
as either type A or B, but store them as types C or D, using either key
type K or T:
class ItemAccessor {
operator A() { ... } // coerce to A
operator B() { ...}
ItemAccessor operator=(C value) {
...
}
ItemAccessor operator=(D value) {
...
}
ItemAccessor(MyCollection col, K idx) { ... }
ItemAccessor(MyCollection col, T idx) { ... }
}
class MyCollection {
ItemAccessor operator[](K idx) { return ItemAccessor(this, idx);}
ItemAccessor operator[](T idx) { return ItemAccessor(this, idx);}
}
In Cython this would be represtented rather different:
class MyCollection:
A __getitem__(K idx)
A __getitem__(T idx)
B __getitem__(K idx) # note: overloads on return value...
B __getitem__(T idx)
void __setitem__(K idx, A value)
void __setitem__(T idx, A value)
void __setitem__(K idx, B value)
void __setitem__(T idx, B value)
So it's not too bad :-) A combinatorial explosion happens but I don't
worry too much, in practice it's not likely to become large.
--
Dag Sverre
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev