void oldWay(string[string] environment)
{
    auto envz = new const(char)*[environment.length + 1];
    int pos = 0;
    foreach (var, val; environment)
        envz[pos++] = (var~'='~val~'\0').ptr;

    exec(envz);
}

void newWay(string[string] environment)
{
    auto buf = staticAppender!(4096, char)();
    StaticArray!(64, size_t) envpBuf;
    size_t[] envp = envpBuf.get(environment.length + 1);

    size_t pos;
    foreach (var, val; environment)
    {
        envp[pos++] = buf.data.length;
        buf.put(var);
        buf.put('=');
        buf.put(val);
        buf.put('\0');
    }

    // Convert offsets to pointers in-place
    auto envz = cast(const(char)*[])envp;
    foreach (n; 0..pos)
        envz[n] += cast(size_t)buf.data.ptr;

    exec(envz);
}

I just thought of something!
I don't comment here often, but I want to express my opinion:

Currently D, being a system language, offers full control over the allocation method, be it the stack or the heap. The helpers above show how flexible it is in doing custom optimized stuff if one wants to. But there's an obvious drawback, quoting Vladimir: "the code is quite more verbose, even with the helper types. It's no longer obvious at a glance what the code is doing."

But think for a moment - does the programmer usually needs to choose the allocation method? Why explicit is default?

It could be the other way around:

void oldWay(string[string] environment)
{
const(char)* envz[environment.length + 1]; // Compiler decides whether to use stack or heap.
    int pos = 0;
    foreach (var, val; environment)
envz[pos++] = (var~'='~val~'\0').ptr; // Use appender. Use stack and switch to heap if necessary
    exec(envz);
}

How nifty would that be, don't you think?

Another benefit could be that the compiler could adjust the stack allocation limit per architecture, and probably it could be defined as a command line parameter, e.g. when targeting a low end device.

This principle could work on fields other than allocation, e.g. parameter passing by ref/value. The programmer needs to only specify whether he wants a copy or the actual value, and the compiler would decide the optimal way to pass it.
e.g.:

immutable int n;
func(n); // by value

immutable int arr[30];
func(arr); // by ref

But these are probably suggestions for D3 or something... Too drastic :)

Reply via email to