Walter Bright:

How much often do I need to write a function like foo?
I think it's uncommon.

I suspect that is a guess.

I have just studied all usages of out arguments in my code, and I have never left an out argument uninitialized inside the function body. When I use an out argument, I always put something inside it in the function body.

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

I have also taken a look at Phobos. I have not done an equivalent study on the Phobos code, but I have seen that out arguments are uncommon in Phobos. The following are almost all the usages:


void getTimes(in char[] name,
              out SysTime accessTime,
              out SysTime modificationTime)
{
    version(Windows)
    {
        with (getFileAttributesWin(name))
        {
accessTime = std.datetime.FILETIMEToSysTime(&ftLastAccessTime); modificationTime = std.datetime.FILETIMEToSysTime(&ftLastWriteTime);
        }
    }
    else version(Posix)
    {
        stat_t statbuf = void;

        cenforce(stat(toStringz(name), &statbuf) == 0, name);

        accessTime = SysTime(unixTimeToStdTime(statbuf.st_atime));
modificationTime = SysTime(unixTimeToStdTime(statbuf.st_mtime));
    }
}


real remquo(real x, real y, out int n) @trusted nothrow @nogc /// ditto
{
    version (Posix)
        return core.stdc.math.remquol(x, y, &n);
    else
        assert (0, "remquo not implemented");
}




real frexp(real value, out int exp) @trusted pure nothrow @nogc
{
    ushort* vu = cast(ushort*)&value;
    long* vl = cast(long*)&value;
    int ex;
    alias F = floatTraits!(real);

    ex = vu[F.EXPPOS_SHORT] & F.EXPMASK;
    static if (real.mant_dig == 64)     // real80
    {
        if (ex)
        {   // If exponent is non-zero
            if (ex == F.EXPMASK) // infinity or NaN




static void prepareStream(ref File file, DWORD stdHandle, string which, out int fileDescriptor, out HANDLE handle)
    {
        fileDescriptor = file.isOpen ? file.fileno() : -1;
if (fileDescriptor < 0) handle = GetStdHandle(stdHandle);
        else                      handle = file.windowsHandle;

        DWORD dwFlags;
        if (GetHandleInformation(handle, &dwFlags))
        {
            if (!(dwFlags & HANDLE_FLAG_INHERIT))
            {
                if (!SetHandleInformation(handle,
                                          HANDLE_FLAG_INHERIT,
                                          HANDLE_FLAG_INHERIT))




    /// Common case of getting integer and boolean options.
int getOption(SocketOptionLevel level, SocketOption option, out int32_t result)
    {
        return getOption(level, option, (&result)[0 .. 1]);
    }



  void read(out byte x);
  void read(out ubyte x);       /// ditto
  void read(out short x);       /// ditto
  void read(out ushort x);      /// ditto
  void read(out int x);         /// ditto
  void read(out uint x);        /// ditto
  void read(out long x);        /// ditto
  void read(out ulong x);       /// ditto
  void read(out float x);       /// ditto
  void read(out double x);      /// ditto
  void read(out real x);        /// ditto
  void read(out ifloat x);      /// ditto
  void read(out idouble x);     /// ditto
  void read(out ireal x);       /// ditto
  void read(out cfloat x);      /// ditto
  void read(out cdouble x);     /// ditto
  void read(out creal x);       /// ditto
  void read(out char x);        /// ditto
  void read(out wchar x);       /// ditto
  void read(out dchar x);       /// ditto



dchar decodeFront(S)(ref S str, out size_t numCodeUnits)
if (!isSomeString!S && isInputRange!S && isSomeChar!(ElementType!S))
in
{
    assert(!str.empty);
}
out (result)
{
    assert(isValidDchar(result));
}
body
{
    immutable fst = str.front;

    if (fst < codeUnitLimit!S)
    {




    void checkName(ref string s, out string name) // rule 5
    {
        mixin Check!("Name");

        if (s.length == 0) fail();
        int n;
        foreach(int i,dchar c;s)
        {
            if (c == '_' || c == ':' || isLetter(c)) continue;
            if (i == 0) fail();
            if (c == '-' || c == '.' || isDigit(c)
                || isCombiningChar(c) || isExtender(c)) continue;
            n = i;
            break;
        }
        name = s[0..n];
        s = s[n..$];
    }




private void regProcessNthValue(HKEY hkey, scope void delegate(scope LONG delegate(DWORD, out string)) dg)
{
    DWORD cValues;
    DWORD cchValueMaxLen;

immutable res = regGetNumValues(hkey, cValues, cchValueMaxLen);
    assert(res == ERROR_SUCCESS);

    wchar[] sName = new wchar[cchValueMaxLen + 1];

    dg((DWORD index, out string name)
    {
        DWORD cchName;
immutable res = regEnumValueName(hkey, index, sName, cchName);
        if (res == ERROR_SUCCESS)
        {
            name = toUTF8(sName[0 .. cchName]);
        }
        return res;
    });
}


How many of such Phobos cases leave on purpose not explicitly initialized an out argument inside the function body?

Bye,
bearophile

Reply via email to