On Friday, 12 April 2013 at 14:58:10 UTC, Manu wrote:
I didn't see any attempt to index the array by key in this case. That's what an AA is for, and it's not being used here, so it's not a job for an
AA.

Sorry, not following.

Are you suggesting to use a dynamic array for creating processes, but an associative array for examining the current process's environment?

I wouldn't use env ~= "FOO=BAR";
I would use env ~= EnvVar("FOO", "BAR");
Or whatever key/value pair structure you like.

OK, but I don't see how it changes your argument. Also, you mentioned string[] earlier.

Well it seemed appropriate. I can't understand what's so wildly complex
that it would make code utterly unmaintainable, and error prone.

I did not say it would be _utterly_ unmaintainable or error prone. Just more so.

It starts as soon as the majority agree it's important enough to enforce.
Although I think a tool like: char[len] stackString; would be a
super-useful tool to make this considerably more painless. Some C compilers
support this.

I believe this is the feature:

http://en.wikipedia.org/wiki/Variable-length_array

It is part of C99.

-------------------------------------------------------------

Earlier today, I wrote:

Please rewrite some part of std.process with performance in mind, and post it here for review. This way, we can analyze the benefits and drawbacks based on a concrete example, instead of vapor and hot air.

I've tried doing this myself, for the bit of code you brought up (constructing environment variables). Here's what I ended up with:

-------------------------------------------------------------

import std.array;

private struct StaticAppender(size_t SIZE, T)
{
    T[SIZE] buffer = void;
    Appender!(T[]) appender;
    alias appender this;
}

/// Returns a struct containing a fixed-size buffer and an
/// appender. The appender will use the buffer (which has
/// SIZE elements) until it runs out of space, at which
/// point it will reallocate itself on the heap.
auto staticAppender(size_t SIZE, T)()
{
    StaticAppender!(SIZE, T) result;
    result.appender = appender(result.buffer[]);
    return result;
}

/// Allows allocating a T[] given a size.
/// Contains a fized-size buffer of T elements with SIZE
/// length. When asked to allocate an array with
/// length <= than SIZE, the buffer is used instead of
/// the heap.
struct StaticArray(size_t SIZE, T)
{
    T[SIZE] buffer = void;
    T[] get(size_t size)
    {
        if (size <= SIZE)
        {
            buffer[0..size] = T.init;
            return buffer[0..size];
        }
        else
            return new T[size];
    }
}

// --------------------------------------------------------

void exec(const(char)*[] envz) { /+ ... +/ }

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);
}

-------------------------------------------------------------

As you can see, the code is quite more verbose, even with the helper types. It's no longer obvious at a glance what the code is doing. Perhaps you can come up with better abstractions?

Reply via email to