October 25, 2019
Why does


/** Array-overload for `startsWith` with no explicit predicate predicate. */
bool startsWith(T)(scope const(T)[] haystack,
                   scope const(T)[] needle)
{
    if (haystack.length >= needle.length)
    {
        return haystack[0 .. needle.length] == needle; // range check is elided by LDC in release builds
    }
    return false;
}

/** Array-overload for `skipOver` with no explicit predicate predicate. */
bool skipOver(T)(scope ref const(T)[] haystack,
                 scope const(T)[] needle)
{
    if (startsWith(haystack, needle))
    {
        haystack = haystack[needle.length .. $];
        return true;
    }
    return false;
}

///
@safe pure nothrow @nogc unittest
{
    string x = "beta version";
    assert(x.skipOver("beta"));
}


fail to compile as


array_algorithm.d(59,22): Error: template `array_algorithm.skipOver` cannot deduce function from argument types `!()(string, string)`, candidates are:
    assert(x.skipOver("beta"));
                     ^
array_algorithm.d(44,6):        `skipOver(T)(ref scope const(T)[] haystack, scope const(T)[] needle)`
bool skipOver(T)(scope ref const(T)[] haystack,
October 25, 2019
On Friday, 25 October 2019 at 06:59:07 UTC, Per Nordlöw wrote:
> /** Array-overload for `skipOver` with no explicit predicate predicate. */
> bool skipOver(T)(scope ref const(T)[] haystack,
>                  scope const(T)[] needle)

Found it.

The parameter `haystack` must be qualified with inout instead of const because it's `ref`.

bool skipOver(T)(scope ref inout(T)[] haystack,
                 scope const(T)[] needle)
{
    if (startsWith(haystack, needle))
    {
        haystack = haystack[needle.length .. $];
        return true;
    }
    return false;
}

Why?