July 29, 2016
On Friday, July 29, 2016 14:14:49 Dicebot via Digitalmars-d wrote:
> On 07/29/2016 02:05 PM, Jonathan M Davis via Digitalmars-d wrote:
> > On Friday, July 29, 2016 02:55:14 Walter Bright via Digitalmars-d wrote:
> >> On 7/29/2016 1:34 AM, Jonathan M Davis via Digitalmars-d wrote:
> >>> I've always looked at D's ref as being essentially the same as C++'s &
> >>> except that it's not considered to be part of the type, just attached to
> >>> it
> >>> in a way that doesn't propagate. The same with with in or out. I just
> >>> don't
> >>> see how it even makes conceptual sense for ref to be an attribute of the
> >>> function itself.
> >>
> >> C++'s & is a bizarre type constructor in that it has completely wacky and
> >> special cased behavior in just about everything involving types,
> >> including
> >> type deduction, type inference, overloading, etc. For example, you can't
> >> have a pointer to a ref. Or a ref of a ref. Sometimes the ref is
> >> considered
> >> part of the type, sometimes not. Etc.
> >>
> >> With D, making it a sort of storage class completely sidesteps that mess.
> >
> > I understand that part. It's treating it like a function attribute that
> > makes no sense to me. Even if it's not treated as part of the return type
> > exactly, it's still the return type that it's affecting, not the function.
> > ref, in, and out are all in this kind of weird place where they affect a
> > type without being part of the type, and I'm guessing that because of how
> > oddball they are, there really wasn't a good way to deal with ref on the
> > return type, since it wasn't actually part of the type, so in the
> > implementation, it got tied to the function instead rather than trying to
> > add a new concept to the compiler. So, I guess that from an implementation
> > perspective, it makes some sense, but it's still downright weird given
> > that
> > ref really has to do with the return type and not the function itself,
> > even
> > if ref is a storage class rather than actually being part of the type.
>
> What you want it contradictory to the concept of "storage class".

Why? I thought the the whole idea of "storage class" was that it was an attribute that was applied to a type that wasn't actually part of the type. Certainly, based on past discussions on the topic, it seems to be that the term is used for pretty much anything that gets applied to a type that isn't actually part of the type. And that's definitely what happens with ref.

- Jonathan M Davis

July 29, 2016
On 07/29/2016 03:55 PM, Jonathan M Davis via Digitalmars-d wrote:
> On Friday, July 29, 2016 14:14:49 Dicebot via Digitalmars-d wrote:
>> What you want it contradictory to the concept of "storage class".
> 
> Why? I thought the the whole idea of "storage class" was that it was an attribute that was applied to a type that wasn't actually part of the type. Certainly, based on past discussions on the topic, it seems to be that the term is used for pretty much anything that gets applied to a type that isn't actually part of the type. And that's definitely what happens with ref.
> 
> - Jonathan M Davis

Storage class has to attach to some symbol to modify its semantics without affecting the type, it doesn't apply to type at all. Usually it is a variable and that comes naturally but in case of function return value / parameters the only available symbol is function itself - contrary to variables, parameters are not available as independent symbols AFAIK.

That said, `ref` isn't a 100% storage class, otherwise `alias Foo = ref int function ( )` wouldn't work. Judging by only observable semantics I'd say it is more akin to type qualifier contrary to what spec says - but qualifier of function type.
July 30, 2016
On Friday, 29 July 2016 at 04:44:16 UTC, Timon Gehr wrote:
> My parser accepts the following:
>
> int function(int,int)ref functionPointer;
>
> I wasn't really aware that this was illegal in DMD. (Other function attributes, such as pure, are accepted.)
>
> In fact, even the following is disallowed:
> int foo(int)ref{}
>
>
> Should I file an enhancement request?

That doesn't fix the above mentioned problem, as ref bind to the variable rather than the type.

postfix ref is not accepted because it can only apply to the type I guess. This is one more example of design being unprincipled to boot.
July 30, 2016
On 30.07.2016 04:49, deadalnix wrote:
> On Friday, 29 July 2016 at 04:44:16 UTC, Timon Gehr wrote:
>> My parser accepts the following:
>>
>> int function(int,int)ref functionPointer;
>>
>> I wasn't really aware that this was illegal in DMD. (Other function
>> attributes, such as pure, are accepted.)
>>
>> In fact, even the following is disallowed:
>> int foo(int)ref{}
>>
>>
>> Should I file an enhancement request?
>
> That doesn't fix the above mentioned problem, as ref bind to the
> variable rather than the type.
>

How does it not fix the problem? int function(int,int)ref is the type of a ref-return function.

> postfix ref is not accepted because it can only apply to the type I
> guess.

How does it apply to the type?

This is one more example of design being unprincipled to boot.

Well, it's more or less reasonable save for the parser inconsistencies.
July 30, 2016
On Saturday, 30 July 2016 at 07:10:30 UTC, Timon Gehr wrote:
> How does it not fix the problem? int function(int,int)ref is the type of a ref-return function.
>

Because storage class binding are already ambiguous and

>> postfix ref is not accepted because it can only apply to the type I
>> guess.
>
> How does it apply to the type?
>
> This is one more example of design being unprincipled to boot.
>
> Well, it's more or less reasonable save for the parser inconsistencies.


August 04, 2016
On 2016-07-28 10:33, Ethan Watson wrote:

> 4) Forward declaring a function prototype means I can never declare that
> function elsewhere (say, for example, with a mixin)

You mean like this:

import std.stdio;

void foo();

void foo()
{
    writeln("asd");
}

void main()
{
    foo();
}

That works for me [1]. It was reported by Manu and fixed in 2012 [2].

[1] https://dpaste.dzfl.pl/c6b9355158cf
[2] https://issues.dlang.org/show_bug.cgi?id=8108

-- 
/Jacob Carlborg
August 04, 2016
On 29 July 2016 at 07:34, Steven Schveighoffer via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> On 7/28/16 4:16 PM, Jonathan M Davis via Digitalmars-d wrote:
>>
>> On Thursday, July 28, 2016 01:49:35 Walter Bright via Digitalmars-d wrote:
>>>
>>> On 7/28/2016 1:33 AM, Ethan Watson wrote:
>>>>
>>>> 1) Declaring a function pointer with a ref return value can't be done without workarounds.
>>>>
>>>> Try compiling this:
>>>>
>>>> ref int function( int, int ) functionPointer;
>>>>
>>>> It won't let you, because only parameters and for loop symbols can be
>>>> ref
>>>> types. Despite the fact that I intend the function pointer to be of a
>>>> kind that returns a ref int, I can't declare that easily. Easy, declare
>>>> an alias, right?
>>>>
>>>> alias RefFunctionPointer = ref int function( int, int );
>>>
>>>
>>> C/C++ have essentially the same problem, if you want to declare a
>>> function
>>> pointer parameter that has different linkage.
>>>
>>> The trouble is there's an ambiguity in the grammar. I don't really have anything better than the two step process you outlined.
>>
>>
>> Well, if we decided to make parens with ref legal, then we could make it work. e.g.
>>
>> ref(int) function(int, int) functionPointer;
>>
>> Now, I don't know of any other case where you'd actually use parens with
>> ref
>> if it were legal, but it would solve this particular case if we wanted to
>> provide a way around the ambiguity.
>
>
> No, because that implies a type-modifier. ref does not modify the type at all, it just specifies the storage class.

Ah yes, one of the most fundamental and terrible mistake in D ;)
August 04, 2016
On 29 July 2016 at 16:51, Jonathan M Davis via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> On Friday, July 29, 2016 08:29:19 Timon Gehr via Digitalmars-d wrote:
>> On 29.07.2016 06:52, Jonathan M Davis via Digitalmars-d wrote:
>> > On Friday, July 29, 2016 06:44:16 Timon Gehr via Digitalmars-d wrote:
>> >> My parser accepts the following:
>> >>
>> >> int function(int,int)ref functionPointer;
>> >>
>> >> I wasn't really aware that this was illegal in DMD. (Other function attributes, such as pure, are accepted.)
>> >>
>> >> In fact, even the following is disallowed:
>> >> int foo(int)ref{}
>> >>
>> >>
>> >> Should I file an enhancement request?
>> >
>> > Except that ref isn't a function attribute.
>>
>> Yes it is.
>>
>> int x;
>> ref{
>>      int foo(){ return x;}
>> }
>> pragma(msg, typeof(&foo()));
>
> That's downright bizzarre given that ref applies to the return type and not to the this pointer (and that function doesn't even have a this pointer, since it's not a member function).
>
>> > It's an attribute on the return type.
>>
>> There is no such thing. Types cannot have attributes.
>
> Sure they can. e.g.
>
> auto func(ref int param) {...}
>
> The same with in and out. They apply to the type of the parameter without actually being part of it.
>
>> > So, it doesn't make sense for it to be on the right. That would be
>> > like having the const on the right-hand side of a member function apply to
>> > the return type rather than the function itself.
>> > ...
>>
>> You have it backwards.
>
> It looks to me like the compiler is treating ref in a schizophrenic manner given that when it's used on a parameter, it treats it as part of the parameter, whereas with the return type, it's treating it as a function attribute instead of associating it with the return type. I'd guess that that stems from the fact that while ref is really supposed to be associated with the type, it's not actually part of the type.

Bingo! But it's much deeper than that. ref is a disaster. Use it to
any real extent; in particular, binding (or fabricating bindings) to
extern(C++) code, and you will see just how fast it breaks down in the
most horrific of ways (almost always resulting in text mixin). I would
fork D just to fix ref!
August 04, 2016
On 29 July 2016 at 19:55, Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> On 7/29/2016 1:34 AM, Jonathan M Davis via Digitalmars-d wrote:
>>
>> I've always looked at D's ref as being essentially the same as C++'s &
>> except that it's not considered to be part of the type, just attached to
>> it
>> in a way that doesn't propagate. The same with with in or out. I just
>> don't
>> see how it even makes conceptual sense for ref to be an attribute of the
>> function itself.
>
>
> C++'s & is a bizarre type constructor in that it has completely wacky and special cased behavior in just about everything involving types, including type deduction, type inference, overloading, etc. For example, you can't have a pointer to a ref. Or a ref of a ref. Sometimes the ref is considered part of the type, sometimes not. Etc.
>
> With D, making it a sort of storage class completely sidesteps that mess.

But introduces a MUCH bigger mess in its place. D's ref is absolute torture past the most simple of cases. The design doesn't scale, it's one gigantic uncontrollable edge case built into the core of the language, with no tools to wrangle or manage. I've never had such an agonizing time with C++'s & as I have with ref in D, and I've had a LOT of agonizing time with C++ ;)
August 04, 2016
On Thursday, 4 August 2016 at 12:44:49 UTC, Manu wrote:
> On 29 July 2016 at 16:51, Jonathan M Davis via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>> [...]
>
> Bingo! But it's much deeper than that. ref is a disaster. Use it to
> any real extent; in particular, binding (or fabricating bindings) to
> extern(C++) code, and you will see just how fast it breaks down in the
> most horrific of ways (almost always resulting in text mixin). I would
> fork D just to fix ref!

I might sound stupid, but there is a better way than forking:

1) Work out a _good_ D improvement proposal and submit it for review to https://github.com/dlang/DIPs (exact process is explained over there)
2) Once accepted, send a PR