<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 5 December 2013 11:02, Jonathan M Davis <span dir="ltr"><<a href="mailto:jmdavisProg@gmx.com" target="_blank">jmdavisProg@gmx.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">On Wednesday, December 04, 2013 16:38:54 H. S. Teoh wrote:<br>
> What about a new overload that takes an output range instead of<br>
> returning a string?<br>
<br>
</div>I would have thought that that would be the obvious way to solve the problem.<br>
In general, I think that when a function allocates any kind of string or array<br>
which it returns, we should overload it with a version that takes an output<br>
range. In many cases, it would probably even make sense to make the default<br>
just use std.array.appender and make it so that only the output range overload<br>
is really doing any work.<br></blockquote><div><br></div><div>This seems the intuitive approach to me.</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

What to do in cases of allocation where we're not dealing with arrays being<br>
returned is a tougher question, and I think that that starts going into custom<br>
allocator territory, but for arrays, output ranges are definitely the way to go<br>
IMHO.<br></blockquote><div><br></div><div>You mean for internal working buffers?</div><div>It get's tricky. In my experience, many functions can use alloca, with a fallback in the event of very large workspaces.</div>
<div>In the event of very large workspaces, it is often possible to break the process into stages which allow an iterative use of a smaller alloca-ed buffer if the function doesn't perform highly random access on the working data.<br>
</div><div>In the event of large workspace and heavily randomised access to the working dataset (ie, difficult to avoid one large allocation), then and only then, maybe start thinking about receiving an allocator to work with (default arg to a gc allocator), or, if it's a large complex process, break the process into sub-functions which the user can issue, and they will then inherit ownership and management of the workspace, which they can treat how they like.</div>
<div><br></div><div>These are some of my approaches. Almost all code I write must never allocate, except for functions that produce new allocations, where either receiving an output range or an allocator seems intuitive.</div>
<div><br></div><div>The most important question to ask is 'can this function possibly be called recursively?'. Many library functions are effectively leaf functions, and can't lead back into user code via any path, which means alloca is safe to use liberally. If there is potential for a recursive call, then i guess you need to start preferring receiving allocators or output ranges, unless the alloca is in the order of a normal function's stack usage (<1kb-ish?).</div>
</div></div></div>