July 10, 2014
On Thursday, 10 July 2014 at 18:39:48 UTC, Walter Bright wrote:
> On 7/10/2014 8:29 AM, Sean Kelly wrote:
>> And I
>> know I'm not alone. Robert's struggle with getting std.logger accepted is the
>> stuff told to children around the campfire so they don't venture out into the dark.
>
> If it makes you feel better, it happens to me too. Everyone assumes someone else is responsible for pulling, and the end result is nothing happens. For example, this one:
>
> https://github.com/D-Programming-Language/dmd/pull/3613

I expect it happens to you even more often given your status.
With the one month limit on pending pull requests I proposed
though, maybe the author of a pull request could simply ask for
comments when that time is up and if there are none he just pulls
it himself.  Worst case the pull could be reverted later.
July 10, 2014
On 07/10/2014 05:59 PM, Dicebot via Digitalmars-d wrote:
> On Thursday, 10 July 2014 at 15:52:45 UTC, Andrei Alexandrescu wrote:
>> On 7/10/14, 8:29 AM, Sean Kelly wrote:
>>> Robert's struggle with getting std.logger accepted is the stuff told to children around the campfire so they don't venture out into the dark.
>>
>> Actually we use his logger at Facebook quite extensively (and
>> happily). -- Andrei
>
> And I still waiting for him to call for next formal review / voting round ;)
please, lets get cracking
July 10, 2014
On 7/10/2014 11:58 AM, H. S. Teoh via Digitalmars-d wrote:
> I didn't exactly go out of my way to *hide* my real name, y'know -- it's
> right on my github profile in a prominent font if you'd only click on my
> pseudonym.  ;-) Surely it's not *that* hard?

I know it isn't hard, but it's a pointless indirection and shouldn't be a virtual function :-)

July 10, 2014
On 7/10/2014 11:46 AM, Andrei Alexandrescu wrote:
> On 7/10/14, 11:39 AM, Walter Bright wrote:
>> On 7/10/2014 8:29 AM, Sean Kelly wrote:
>>> And I
>>> know I'm not alone. Robert's struggle with getting std.logger accepted
>>> is the
>>> stuff told to children around the campfire so they don't venture out
>>> into the dark.
>>
>> If it makes you feel better, it happens to me too. Everyone assumes
>> someone else is responsible for pulling, and the end result is nothing
>> happens. For example, this one:
>>
>> https://github.com/D-Programming-Language/dmd/pull/3613
>
> Well I just pulled that. -- Andrei

Whatever it takes to get it pulled! :-)

Tanks!
July 10, 2014
On 07/10/2014 06:05 PM, Sean Kelly via Digitalmars-d wrote:
> On Thursday, 10 July 2014 at 15:52:45 UTC, Andrei Alexandrescu wrote:
>> On 7/10/14, 8:29 AM, Sean Kelly wrote:
>>> Robert's struggle with getting std.logger accepted is the stuff told to children around the campfire so they don't venture out into the dark.
>>
>> Actually we use his logger at Facebook quite extensively (and
>> happily). -- Andrei
>
> Yep, it's good!  But still not in Phobos despite his efforts.  At this point I honestly don't know what the blocker is either.  Maybe just inertia.
It is not just the logger.

I have multiple PRs who addressed all the critics, but are still getting
nowhere it seams.
I find myself rebasing from time to time just to get an autotester run
to see if it still merges and performs.

I know this is a bit OT and personal, but could somebody please merge indexOfNeither aka indexOfNone. I just hate to copy this function from one personal project to the next.
July 10, 2014
I've been working on a proposal for ownership and borrowing since some time, and I seem to have come to a very similar result as you have. It is not really ready, because I keep discovering weaknesses, and can only work on it in my free time, but I'm glad this topic is finally addressed. I'll write about what I have now:

First of all, as you've already stated, scope needs to be a type modifier (currently it's a storage class, I think). This has consequences for the syntax of any parameters it takes, because for type modifiers there need to be type constructors. This means, the `scope(...)` syntax is out. I suggest to use template instantiation syntax instead: `scope!(...)`, which can be freely combined with the type constructor syntax: `scope!lifetime(MyClass)`.

Explicit lifetimes are indeed necessary, but dedicated identifiers for them are not. Instead, it can directly refer to symbol of the "owner". Example:

    int[100] buffer;
    scope!buffer(int[]) slice;

Instead of lifetime intersections with `&` (I believe Timon proposed that in the original thread), simply specify multiple "owners": `scope!(a, b)`. This works, because as far as I can see there is no need for lifetime unions, only intersections.

A problem that has been discussed in a few places is safely returning a slice or a reference to an input parameter. This can be solved nicely:

    scope!haystack(string) findSubstring(
        scope string haystack,
        scope string needle
    );

Inside `findSubstring`, the compiler can make sure that no references to `haystack` or `needle` can be escape (an unqualified `scope` can be used here, no need to specify an "owner"), but it will allow returning a slice from it, because the signature says: "The return value will not live longer than the parameter `haystack`."

    // fixed-size arrays (new syntax of Kenji's PR)
    string[$] text = "Old McDonald had a farm.";
    auto sub = findSubstring(text, "had");
    // typeof(sub) is scope!text(string),
    // `haystack` gets substituted by `text`
    assert(sub == "had a farm".);

Have multiple parameters? No problem:

    scope!(a,b)(string) selectOneAtRandom(
        scope string a,
        scope string b
    );
    // => a _and_ b will outlive return value

For methods, `scope!this` can be used to. It's really no different from other parameters, as `this` is just a special implicit parameter.

There is also a nice extension: `scope!(const owner)`. This means, that as long as the value designated as such live, `owner` will be treated as const.

An interesting application is the old `byLine` problem, where the function keeps an internal buffer which is reused for every line that is read, but a slice into it is returned. When a user naively stores these slices in an array, she will find that all of them have the same content, because they point to the same buffer. See how this is avoided with `scope!(const ...)`:

struct ByLineImpl(Char, Terminator) {
private:
    Char[] line;
    // ...

public:
    // - return value must not outlive `this` (i.e. the range)
    // - as long as the return value exists, `this` will be const
    @property scope!(const this)(Char[]) front() const {
        return line;
    }
    void popFront() { // not `const`, of course
        // ...
    }
    // ...
}

void main() {
    alias Line = const(char)[];
    auto byline = stdin.byLine();
    foreach(line; byline) {
        write(line); // OK, `write` takes its parameters as scope
        // (assuming the widespread usage of scope throughtout Phobos)
    }
    Line[] lines;
    foreach(line; byline) {
        lines ~= line;
        // ERROR: `line` has type scope!(const byline)(Line), not Line
    }
    // let's try to work around it:
    scope!(const byline)(Line)[] clines;
    foreach(line; byline) {     // ERROR: `byline` is const
        clines ~= line;
    }
    // => nope, won't work
    // another example, to show how it works:
    auto tmp = byline.front;    // OK
    // `byline` is const as long as `tmp` exists
    write(byline.front);        // OK, `front` is const
    byline.popFront();          // ERROR: `byline` is const
}

Describing what happens here: As long as any variable (or temporary) with the type `scope!(const byline)` exists, `byline` itself will be treated as const. "Exists" in this case only referes to lexical scope: A variable is said to "exist" from the point it is declared, to the end of the scope it's declared in. Loops, gotos, and exceptions don't have an effect. This means that it can be easily checked by the compiler, without it having to perform complicated control flow analysis.

I also thought about allowing `scope!return` for functions, to specify that it a value will not outlive the value returned from the function, but I'm not sure whether there is an actual use case, and the semantics are not clear.

An open question is whether there needs to be an explicit designation of GC'd values (for example by `scope!static` or `scope!GC`), to say that a given values lives as long as it's needed (or "forever").

Specifying an owner in the type also integrates naturally with allocators. Assuming an allocator releases all of it's memory to operating system when it is destroyed, there needs to be a guarantee that none of its contents is referenced anymore at this point. This can be achieved by returning a borrowed reference:

    struct MyAllocator {
        scope!this(T) alloc(T)() if(T == class) {
            // ...
        }
    }

Note that this does not preclude the allocator from doing garbage collection while it exists; in this manner, `scope!GC` might just be an application of this pattern instead of a special syntax.

Now, for the problems:

Obviously, there is quite a bit of complexity involved. I can imagine that inferring the scope for templates (which is essential, just as for const and the other type modifiers) can be complicated.

On the upside, at least it requires no control or data flow analysis. It's also a purely additive change: If implemented right, no currently working code will break.

Then I encountered the following problem, and there are several different variations of it:

    struct S {
        int* p;
        void releaseBuffer() scope {
            // `scope` in the signature applies to `this`
            free(this.p);
            this.p = null;
        }
    }
    int bar(scope ref S a, scope int* b) {
        a.releaseBuffer();
        return *b; // use after free
    }
    S s;
    bar(s, s.p);

The root cause of the problem here is the call to `free()`. I _believe_ the solution is that `free()` (and equivalent functions of allocators as well as `delete`) must not accept scope parameters. More realistic candidates for such situations are destructors in combination with move semantics. Therefore, `~this()` needs to be marked as scope, too, for it to be callable on a borrowed object. If a scope object has a non-scope destructor, but no scope one, and is going to be destroyed, this needs to be a compile error. (Rust avoids that problem by making any object const while there are borrowed references, but this requires its complex borrow checker, which we should avoid for D.)

I also have a few ideas about owned types and move semantics, but this is mostly independent from borrowing (although, of course, it integrates nicely with it). So, that's it, for now. Sorry for the long text. Thoughts?
July 10, 2014
On Thursday, 10 July 2014 at 20:10:38 UTC, Marc Schütz wrote:
> snip

That's curious. I actually replied to H. S. Teoh in his new thread, but somehow it ended up here...
July 10, 2014
On 7/10/2014 11:49 AM, H. S. Teoh via Digitalmars-d wrote:
> Another thing that might help, is if we can somehow change the default
> sort order on the github PR page. Currently it's defaulted to newest
> first, but that's a horrible default order given our circumstances. A
> much better order is "least recently updated", so that the oldest, most
> ignored PRs will get attention first. Even if they are mostly ignored,
> at least every time somebody goes to that page they'll see it in
> passing, and perhaps decide one day to actually look into what it is. As
> opposed to the current situation of "out of sight, out of mind".


I'd prefer "most recently commented on or updated". That way, the originator can post a ping causing it to bubble up to the top.
July 10, 2014
On 7/10/2014 12:57 PM, Robert Schadek via Digitalmars-d wrote:
> I know this is a bit OT and personal, but could somebody please merge
> indexOfNeither aka indexOfNone. I just hate to copy this function from
> one personal project to the next.

I don't know the PR link nor do I know what pseudonym you use on github, so please help!

I reiterate my complaint that people use "virtual functions" for their github handles. There's no reason to. Who knows that 9il is actually Ilya Yaroshenko? Took me 3 virtual function dispatches to find that out!

Take a look at the contributor list:

https://github.com/D-Programming-Language/phobos/pulls

I'm sure y'all know your own handles, but how many of the others do you know who they are?
July 10, 2014
On Thu, 10 Jul 2014 20:10:36 +0000, Marc Schütz wrote:

> So, that's it, for now. Sorry for the long text.
> Thoughts?

This is crazy interesting, thanks for writing it up.  Need to digest it a bit before offering more feedback.