On 10/17/2012 12:11 AM, Jonathan M Davis wrote:
On Wednesday, October 17, 2012 00:04:49 Timon Gehr wrote:
On 10/16/2012 09:47 PM, jerro wrote:
Hmm. There *is* a delegate being passed to map(). Would that cause
problems? Theoretically it shouldn't, but as you said, if dmd isn't
handling it correctly that could cause problems.
I'm looking at the disassembly of cprod (http://pastebin.com/ngTax6B8)
and there doesn't seem to be a call to _d_allocmemory in it. AFAIK it
should be if the memory for the variables that the delegate uses was
allocated on the heap?
It should certainly allocate a closure. However, we don't want hidden
allocations in Phobos, so an alternate implementation strategy that
captures the input by value would be preferable anyway.
The bug should be reported in each case.
The allocation of closures is pretty much inevitable when we have delegates
and/or non-static Voldemort types.
- Jonathan M Davis
Unless there are compiler bugs of course. Anyway, that is why I was
suggesting to use an alternate implementation strategy.
The following code is free of allocations if the compiler implementation
is correct:
auto cprod(R1,R2)(R1 A, R2 B) {
return zip(sequence!"n"(cast(size_t)0), A.save, B.save, repeat(A),
repeat(B))
.map!(function(a) => chain(
zip(repeat(a[1]), take(a[4].save,a[0])),
zip(take(a[3].save,a[0]+1), repeat(a[2]))
)).joiner;
}
It also works around the issue. (note that I got rid of some UFCS
calls. The reason is that we don't know whether R1 and/or R2 actually
have a member named 'take' or 'repeat' that would hijack the function we
want to call.)
(But you also need to (potentially) escape them in order to trigger the
allocation, so delegates and non-static structs are even useful when
allocating is not an option.)