Dag Sverre Seljebotn wrote:
> Sturla Molden wrote:
>   
>> Sturla Molden skrev:
>>   
>>     
>>> We have the same sematical difference when calling functions:
>>>
>>>    void foobar(int& c);
>>>
>>> the reference c is intialized to alias the argument with which foobar is 
>>> called. But you can never rebind c to alias another object in the local 
>>> scope of foobar. If you assign to c you modify the variable aliased by c.
>>>     
>>>       
> Sorry, this could have been worded better -- references here refers to 
> Python references = C pointers (more or less), not C++ references.
>
>   
>> And as for Python, if we have
>>
>>    c = 5
>>    foobar(c)
>>
>> the value of c cannot be changed as c is immutable.
>>
>> But if we have
>>
>>    from ctypes import c_int
>>    c = c_int(5)
>>    foobar(c)
>>
>> then the call to foobar can change the value of c by assigning to 
>> c.value in its local scope. 
>>
>> In either case, if foobar assigns to c in its local scope (i.e. rebinds 
>> the name), nothing happens to c in the calling scope.
>>
>> This is obviously very different from C++, but in neither case can 
>> foobar rebind the argument in the calling scope.
>>
>> We should not confuse the issues of name binding vs. assignment and 
>> mutability vs. immutability. It's not the same. But Python and C++ 
>> differs in both cases.
>>   
>>     
> Yes, it was you who brought mutability into the mix; I claimed it was 
> irrelevant.
>
> Anyway...you keep stating things that we all know very well. Are you 
> agreeing or disagreeing with my and Stefan's position? Is there a point 
> to this discussion at all?
>
> Specifically:
>
> cdef int x = ...
> cdef MyCppClass *y = ...
> f(x, y)
>
> Do you want f to be allowed, if the arguments are declared as 
> references, to change the value of x and which memory location y points to?
>
> There's no need to go into explaining what C++ does (I'm well aware of 
> it), it's a simple yes or no question, and the question is simply "do we 
> allow this feature of C++ into the Cython language, or do we take 
> another approach instead that looks less strange with Python semantics?".
>
> (Anyway, I think the question is pretty much settled.)
>   
Or perhaps not, the example toki doki posted gets ugly, as one needs to do

foo = vect.at(4)[0] + 10

to get the equivalent of the C++ "foo = vect.at(4) + 10".

So here's some additional proposals:

I)

What we could do is to add a rule that if you have

cdef cppclass MyClass:
    int& at(int idx)

Then Cython will automatically add an "assign_*" method:

cdef MyClass *x = new MyClass(10)
x.assign_at(0, 2) # Cython generates: x.at(0) = 2
print x.at(0) + 10 # at(0) fetches value

I.e.: If the return value is a reference, create a psuedo-method named 
"assign_*" which takes the value to assign as the last argument. (If 
such a method is already declared manually, assume the psuedo-method 
isn't needed?)

II) A common pattern is "void f(const MyStruct& foo)" (i.e. pass a 
pointer just to speed things up, but the contents won't be changed). In 
that case, note that it can be declared in Cython just as

cdef void f(MyStruct foo)

which should work well, Cython will just emit the right code.

III) The case Sturla talked about I think boils down to this:

cdef cppclass MyClass:
    void f(SomeStruct& foo)

In this case, it's not entirely unnatural for Python code to do this

myinstance.f(foostruct)

and have the members of foostruct modified. It does contrast current 
Cython code, but not Python code, I think. But, it seems that one should 
be consistent with the next item:

IV) There's still a problem with "void f(int& foo)" as well as "void 
f(SomeStruct*& foo), in which case we should probably demand

myinstance(&foo)

And then it seems prudent to require it in III as well.

Dag Sverre
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to