Robert Bradshaw wrote:
> On Oct 11, 2008, at 12:24 AM, Greg Ewing wrote:
> 
>> Robert Bradshaw wrote:
>>
>>> It's on the stack, just like literals.
>> What do you mean, "just like literals"? What literal
>> is ever allocated on the stack?
> 
> Array literals are allocated on the stack.
> 
>>> However, one can write
>>>
>>> def foo(x, y):
>>>      cdef double* a
>>>      if x:
>>>          a = [1,2,3,x]
>>>      else:
>>>          a = [1,2,3,y]
>> Now I'm *really* confused. What the heck does that do?
>> Can you provide a C translation?
> 
> 
> Sure. I'm ignoring the implicit conversions that happen for clarity...
> 
> double[4] tmp1;
> double[4] tmp2;
> if (x) {
>      tmp1[0] = 1
>      tmp1[1] = 2
>      tmp1[2] = 3
>      tmp1[3] = x
>      a = tmp1
> }
> else {
>      tmp2[0] = 1
>      tmp2[1] = 2
>      tmp2[2] = 3
>      tmp2[3] = y
>      a = tmp2
> }
> 

I can see that this has many practical usecases etc., still I'm back to 
worrying. If the following concern is valid then I'm -1 on this for the 
coming release, it should at least be postponed.

The reason I worry is that one can write (rather contrived) code like this:

cdef int* a
cdef int* b
for i in range(2):
     a = [1,1,1]
     if i == 0:
         b = a
         b[0] = 2

print b[0] # will print 1...

...which will be rather non-obvious if you do not know *exactly* how the 
allocation etc. works.

The reason this is so bad is because it seems like you are pointing "a" 
to *something else* the second time around the loop, and that "b" should 
continue pointing to the "old" array. (But there is only one array. 
Which is especially counter-intuitive given how this code would work in 
Python. Etc.)

To boil it down a bit, the problem is that

a = [1,1,1]
b = a
a = [1,1,1]

has entirely different semantics from

for i in range(2):
     a = [1,1,1]
     if i == 0: b = a

even though the first example looks exactly like just rolling out the 
latter. At least it is very un-Pythonic.

(I did not actually try the code above, but if it doesn't work then I'd 
counter that the mechanism is so magical that I cannot figure it out :-) )

What do I propose instead?
  a) That the reference-counted heap-allocated array stuff in the wiki 
is implemented first (with a list constructor). So the thing gets the 
semantics of a reference counted array, constructed again each time it 
is assigned (very similar to a Python list).

  b) That simple cases (where the pointer is never reassigned or copied, 
only written/read to/from by indexing) are then optimized to use stack 
allocation instead.

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

Reply via email to