April 15, 2016
On 4/15/16 6:31 PM, Timon Gehr wrote:
> On 15.04.2016 23:56, Steven Schveighoffer wrote:
>>
>> Impossible or difficult to do with the current implementation?
>> ...
>
> What I'm saying is that the check that is currently implemented is not
> adequate for the new case. This is not terribly important though. The
> point was that there needs to be a design effort beyond lifting the
> limitation, and you seemed to claim that the current implementation
> already takes care of the presented issue, which is not the case.
>
> Your ideas are sound though.

I'm sorry, should have put on my standard disclaimer that I am not a compiler writer :) I actually have no idea how this is done in the compiler, just how a compiler should behave as I understand it in my head.

>> I may have said this incorrectly. The language itself wouldn't really be
>> that much more complex. It's the cost of understanding what each of the
>> different inout pools mean.
>
> They would just be named parameters to the function on the type system
> level, similar to template arguments but not causing repeated
> instantiation.

Right, but again: these are named by the writer of the template, not the language, right? In that case, any identifier becomes a modifier. Or are you thinking of something different?

>> The benefit would be quite small, whereas
>> there are obvious places inout makes sense -- the 'this' parameter and
>> the return value.
>> ...
>
> The return value might contain more than one pointer, and functions
> often have more than one parameter.

Of course, but the transference of mutability from parameter to return value is the obvious draw of such a wildcard. In most cases, there is only one return value, and therefore only one pool that needs to be handled.

ref/out parameters can serve as alternate returns as well as composed types.

It's not that functions don't have multiple returns with their own inout, but I don't think it's very common. As we get more and more obscure, the cost/benefit ratio for complexity vs. power gets higher. And already people don't like where we are right now with it.

>> Then there is the syntax that would be required, I'm not sure what that
>> looks like.
>> ...
>
> Anything that is analogous to template parameters, e.g. an additional
> set of arguments with a different delimiter. Many workable
> possibilities. Anyway, it is unlikely to happen.

Especially given the discussion happening here, I agree.

>> Humans are creatures of habit and familiarity. To allow each library to
>> define what words mean what for modifiers would be really difficult to
>> deal with.
>>
>
> I don't see how the library would do that.

Just throwing a strawman out there:

void foo(bingo = inout, zingo = inout)(bingo(int)* x, zingo(int)* y)

So inside foo, bingo is one flavor of inout, zingo is another. This could vary library to library, function to function.

It would work, and be sound design. I would just hate it is all :)

Perhaps you have a better system in mind?

-Steve
April 16, 2016
On 15/04/2016 04:10, Andrei Alexandrescu wrote:
> Commenting it out yields a number of unittest compilation errors,
> neither informative about the root of the problem and indicative as to
> how the parameter solves it.
...
> 2. There needs to be documentation for people working on the standard
> library so they don't need to waste time on their own discovery process.

Perhaps use this, at least for now:

// <Workaround explanation>
alias InOutParam = inout int;

...
    (InOutParam)
    {
        ...
    }

It's less cryptic at the use-site and people can lookup the definition to find an explanation.
April 16, 2016
On 2016-04-15 07:38, Andrei Alexandrescu wrote:

> I think we should deprecate inout. For real. It costs way too much for
> what it does. For all I can tell most of D's proponents don't know how
> it works. -- Andrei

If "inout" is only used as a way avoid code duplication, both when writing the code and the compiler generating the code. Then that can be solved with two steps:

1. Improve the compiler to remove duplicated functions overloaded on constness. That is, they generate the exact same code and and the only difference is the constness of the functions. This is a useful improvement regardless

2. Write a string mixin that duplicates a function three times, one for each type of constness:

// Assuming "inout" is removed from the language and not a keyword anymore

mixin(inout(q{
    inout(T)[] replaceSlice(T)(inout(T)[] s, in T[] slice, in T[] replacement) { ... }
});

The "input" function would need to parse arbitrary D code and create three version of the passed in function declaration, mutable, const and immutable. In theory libdparse could be used for this but it doesn't work at compile time. The downside is that it looks really ugly when defining an inout function.

But, with AST macros it could look like this:

@inout inout(T)[] replaceSlice(T)(inout(T)[] s, in T[] slice, in T[] replacement);

-- 
/Jacob Carlborg
April 16, 2016
(It seems my reply got lost somewhere, reposting...)

On Friday, 15 April 2016 at 19:28:02 UTC, Andrei Alexandrescu wrote:
> A better support for this argument is std.array.replaceSlice at https://github.com/D-Programming-Language/phobos/blob/master/std/array.d#L2594:
>
> inout(T)[] replaceSlice(T)(inout(T)[] s, in T[] slice, in T[] replacement);
>
> So here we are guaranteed that (a) the result type is the same as the first argument, and (b) the first argument is never modified even if a mutable slice is passed.

What are the plans for DIP25's `return` attribute? Because with it, the compiler has enough information to know that the return value aliases `s`:

const(T)[] replaceSlice(T)(const(T)[] s return, in T[] slice, in T[] replacement);

If the function is passed a mutable `s`, its return value can be implicitly convertible to `T[]`.
April 16, 2016
On 16/04/2016 12:40, Marc Schütz wrote:
> What are the plans for DIP25's `return` attribute? Because with it, the
> compiler has enough information to know that the return value aliases `s`:
>
> const(T)[] replaceSlice(T)(const(T)[] s return, in T[] slice, in T[]
> replacement);
>
> If the function is passed a mutable `s`, its return value can be
> implicitly convertible to `T[]`.

AIUI, functions don't have to return part of the parameter tagged with return, it can return anything.

See:
http://wiki.dlang.org/DIP25#Types_of_Result_vs._Parameters
April 17, 2016
Am Fri, 15 Apr 2016 09:44:05 -0400
schrieb Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org>:

inout must go. -- Andrei

Ceterum censeo Carthaginem esse delendam. -- Marcus Porcius Cato
:o)

-- 
Marco

April 16, 2016
On Saturday, 16 April 2016 at 22:06:10 UTC, Marco Leise wrote:
> Am Fri, 15 Apr 2016 09:44:05 -0400
> schrieb Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org>:
>
> inout must go. -- Andrei
>
> Ceterum censeo Carthaginem esse delendam. -- Marcus Porcius Cato
> :o)

What does that have to do with what he said?
Are you comparing him to Cato?
April 17, 2016
On Friday, 15 April 2016 at 20:03:07 UTC, Andrei Alexandrescu wrote:
> We should really do away with the cowboy style of designing language, which sadly Walter and I have been guilty of too often in the past. The slow but sure accretion of complexity of inout is a textbook example of where that leads.
>
> Andrei

This deserves to be a poster with a golden frame. You've got lucky with pure (modulo corner cases) and ctfe, much less lucky with @safe, @trusted, @system, inout, shared, scope, property.

April 17, 2016
On Sunday, 17 April 2016 at 14:30:59 UTC, QAston wrote:
> You've got lucky with pure (modulo corner cases) and ctfe, much less lucky with @safe, @trusted, @system, inout, shared, scope, property.

The @safe troika is a good design (except @safe should be the default), the implementation is lacking though. Ideallists want to make @safe strict now, but break code sometimes even without basic workarounds for memory-safe code. Pragmatists want to avoid breakage but make the subset of @safe code wider, making the definition more complex. There seems to be a stalemate.

scope, if implemented for reference types, wouldn't scale well. It should be the default, with __escape meaning scope(false). I think it's an uphill battle arguing for this, but it is crucial to avoiding GC without runtime checks. At least for non-GC code in a general way.

I think @property is OK. I think the controversy at the time was about optional brackets in function calls, which is different.
April 17, 2016
On Sunday, 17 April 2016 at 16:44:50 UTC, Nick Treleaven wrote:
> The @safe troika is a good design (except @safe should be the default), the implementation is lacking though. Ideallists want to make @safe strict now, but break code sometimes even without basic workarounds for memory-safe code. Pragmatists want to avoid breakage but make the subset of @safe code wider, making the definition more complex. There seems to be a stalemate.

Yeah, but for example rust deals with the same problem with a single keyword.

> scope, if implemented for reference types, wouldn't scale well. It should be the default, with __escape meaning scope(false). I think it's an uphill battle arguing for this, but it is crucial to avoiding GC without runtime checks. At least for non-GC code in a general way.

scope (for function parameters) cannot be implemented in backwards compatible way because a lot of code uses in (which is const^scope)

> I think @property is OK. I think the controversy at the time was about optional brackets in function calls, which is different.
First @property + compiler switch, now @property + deprecated switch. When should I use property? For all the getters? Should I start with property or with member access? Does it even matter because of optional parens? Why do I even need to care about this?

Sure all of the things I've mentioned can be defended. The question is not whether they have a usecase (because all of them do), but whether return on investment for them is good enough and how they interact with the rest of the language.

CTFE does what you'd expect it to do - constant folding is intuitive and requires little to no code changes. Purity is orthogonal to the rest of the language (modulo corner cases) and enables some patterns for immutable value creation. Those (and others - the stuff that's good doesn't come to mind because it works) have higher ROI and aren't as much of a burden for library writers.