February 05, 2013
On Tuesday, 5 February 2013 at 18:33:36 UTC, Andrei Alexandrescu wrote:

>
> Walter and I reviewed the discussion and had a long talk. We are very seriously considering banning the use of & against a ref result from a function

Please, no.

ref T foo();

extern(C) void bar(T*);

bar(&foo()); // how?
February 05, 2013
Timon Gehr <timon.gehr@gmx.ch> wrote:
> On 02/05/2013 09:21 PM, Andrei Alexandrescu wrote:
>>  ...
>>  Also consider the simpler:
>> 
>> ref int id(ref int x) { return x; }
>> ref int id1(ref int x) { return id(x); }
>> ref int id2(ref int x) { return id1(x); }
>> ref int oops(int x) { return id2(x); }
>> 
>> DIP24 addresses that and other similar cases at their core. ...
> 
> Given a noticeable tendency of your latest design proposals, I guess it does so by disallowing the 'ref' keyword in the lexer stage. :o)

What is the noticeable tendency of my latest design proposals?

Andrei
February 05, 2013
<address_is@invalid.invalid> wrote:
> Timon Gehr <timon.gehr@gmx.ch> wrote:
>> On 02/05/2013 09:21 PM, Andrei Alexandrescu wrote:
>>>  ...
>>>  Also consider the simpler:
>>> 
>>> ref int id(ref int x) { return x; }
>>> ref int id1(ref int x) { return id(x); }
>>> ref int id2(ref int x) { return id1(x); }
>>> ref int oops(int x) { return id2(x); }
>>> 
>>> DIP24 addresses that and other similar cases at their core. ...
>> 
>> Given a noticeable tendency of your latest design proposals, I guess it does so by disallowing the 'ref' keyword in the lexer stage. :o)
> 
> What is the noticeable tendency of my latest design proposals?
> 
> Andrei

That was me on the misconfigured phone.

Andrei
February 05, 2013
On 2013-02-05, 23:46, Max Samukha wrote:

> On Tuesday, 5 February 2013 at 18:33:36 UTC, Andrei Alexandrescu wrote:
>
>>
>> Walter and I reviewed the discussion and had a long talk. We are very seriously considering banning the use of & against a ref result from a function
>
> Please, no.
>
> ref T foo();
>
> extern(C) void bar(T*);
>
> bar(&foo()); // how?


    @system T* addressOf(T)(ref T obj)
    {
        static T* id(T* p) { return p; }
        auto idr = cast(T* function(ref T)) id;
        return idr(obj);
    }

    bar(addressOf(foo()); // Like this

It's right there in his post.

-- 
Simen
February 06, 2013
On Tuesday, 5 February 2013 at 21:59:53 UTC, Andrei Alexandrescu wrote:
> Just to make sure: this is about http://forum.dlang.org/thread/ririagrqecshjljcdubd@forum.dlang.org.
>
> Language design is a subjective topic. With time I have learned it's best to not comment very much about it. I have created dozens, maybe hundreds of tidbits of language design and invariably I believe they had obvious merits and negligible drawbacks. The confidence in the quality of my own language designs has decayed exponentially over the years.
>
> I'm telling this to put in perspective my following comment. I think it's awesome that work like yours is discussed and refined in this group. At the same time my opinion is that the design is not appropriate for us. It changes semantics of existing code and fosters a cross-talk between subcomponents that has not been time tested. It is complicated in implementation for a benefit that's not properly motivated. At the top level it solves the wrong problem. As stated: "The challenge is to do better, both in terms of functionality and in terms of syntax, than his proposal: ..." The actual challenge is to make properties work with maximum backward compatibility, minimal surprise, best integration with the rest of the language, and maximum of benefits.
>
>
> Andrei

Okay. But I just want to be clear that you are saying what I am reading, which is that I came to this language too late to really make a difference in it.
February 06, 2013
On 02/05/2013 11:58 PM, Andrei Alexandrescu wrote:
> <address_is@invalid.invalid> wrote:
>> Timon Gehr <timon.gehr@gmx.ch> wrote:
>>> On 02/05/2013 09:21 PM, Andrei Alexandrescu wrote:
>>>>   ...
>>>>   Also consider the simpler:
>>>>
>>>> ref int id(ref int x) { return x; }
>>>> ref int id1(ref int x) { return id(x); }
>>>> ref int id2(ref int x) { return id1(x); }
>>>> ref int oops(int x) { return id2(x); }
>>>>
>>>> DIP24 addresses that and other similar cases at their core.
>>>> ...
>>>
>>> Given a noticeable tendency of your latest design proposals, I guess it
>>> does so by disallowing the 'ref' keyword in the lexer stage. :o)
>>
>> What is the noticeable tendency of my latest design proposals?
>>
>> Andrei
> ...

They were mostly about banning stuff.
February 06, 2013
2013/2/6 Jonathan M Davis <jmdavisProg@gmx.com>
>
> Being able to initially use a public variable and then swap it out later
> for
> property functions when refactoring is generally the reason that I've heard
> for why properties exist in the first place in C#. It's what a number of
> people
> around here seem to think is a core feature of properties, and a core
> feature
> isn't feature creep. And if @property on a variable makes it so that it
> lowers
> to getter and setter property functions (rather than leaving it as a public
> variable with certain restrictions on it), then we don't even have to worry
> about which features of a variable property functions do and don't emulate
> and
> whatever feature creep might appear there. The "variable" would immediately
> match due to the fact that you'd actually end up with property functions.
> You
> just wouldn't have had to do all the boilerplate for it.
>

I fully agree with Andrei.
I can see that swapping public data field to property function call is not
rare, but in almost case, such refactoring also intends to add
encapsulation.

struct S {
    // Before swapping
    int _data;

    // After swapping
    private int _data;
    @property int data() { return _data; }
    @property void data(int n) { enforce(n > 0); _data = n; }
}
S s;
int n = s.data;
s.data = 1;
//int* pdata = &s.data;
// changed to disallowed ... it is mostly intended.

> Unprotected, unchecked member variables that can be get and set without
> > any hooks into the enclosing structure are rare. That's not the case we should help and cater for. When that's the case, the entire object is legitimately a "bag of values" that has only public data.
>
> Really? In my experience they're quite common. It's usually the case that
> not
> all of the variables on a type have pass-through getters and setters, but
> it's
> quite common to have at least a few which do. It's been brought up a
> number of
> times in the past that it would be nice to have @property on variables be
> used
> to avoid the boilerplate code in those cases. I suppose that we could use a
> mixin to solve that problem, but then you wouldn't get any documentation on
> it, since you can't document anything that's mixed in.


Wrapping a field data with property function but also allow accessing to it directly through pointer is quite rare.

struct S {
    // After swapping
    private int _data;
    @property ref int data() { return _data; }  // ref return
    @property void data(int n) { enforce(n > 0); _data = n; }
}
S s;
int n = s.data;  // call getter
s.data = 1;  // call setter, enforce n > 0
int* pdata = &s.data;  // But, if this is allowed,
*pdata = -1;  // this is accidentally allowed... Is this really intended?

To me, it is just a encapsulation breaking.
I'm not sure that it is what you would really expect.

Kenji Hara


February 06, 2013
On Wednesday, February 06, 2013 09:56:40 kenji hara wrote:
> I fully agree with Andrei.
> I can see that swapping public data field to property function call is not
> rare, but in almost case, such refactoring also intends to add
> encapsulation.
> 
> struct S {
>     // Before swapping
>     int _data;
> 
>     // After swapping
>     private int _data;
>     @property int data() { return _data; }
>     @property void data(int n) { enforce(n > 0); _data = n; }
> }
> S s;
> int n = s.data;
> s.data = 1;
> //int* pdata = &s.data;
> // changed to disallowed ... it is mostly intended.

You misunderstand. We don't _want_ taking the address to work. We _want_ the encapsulation. We just don't want to have to write all of the boilerplate code.

The idea is that you want to be able to just make it a variable first, because you don't need to do any extra checks or anything else but get or set the variable. So, having to declare the setters and getters is overkill. The problem is that if you just declare it a variable, then people can take the address of it or pass it by ref - which you don't want. You _want_ the encapsulation up-front. You just don't want to have to bother with all of the boilerplate code required to do it. That's why some of us have suggested making it so that you can mark variables with @property. That then either makes it illegal to do anything with it which you couldn't do with a property function (e.g. take its address), or it simply lowers it to the getters and setters, making it so that you _do_ have the property functions in the beginning. You just don't have to write them explicitly. Then later, if refactoring requires that you add additional checks or other operations to the getter and/or setter, then you explicitly declare the property functions.

- Jonathan M Davis
February 06, 2013
On 2/6/13, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> That's why some of us have suggested
> making it so that you can mark variables with @property.

What Jonathan means is this:

struct S
{
    int var;  // modifiable, can take address
}

Now suppose later you want to turn var into a property:

struct S
{
    @property int var();
    @property void var(int);
}

This potentially breaks code if the user-code was using a pointer to the public var field in the previous version of your library.

So instead we should have the ability to annotate fields with @property:

struct S
{
    @property int var;  // modifiable, can *not* take address
}

There's no run-time cost, but it disallows taking the address of var, and it allows you to introduce property functions in the future without breaking user-code.
February 06, 2013
On 2/5/13 7:15 PM, Zach the Mystic wrote:
> Okay. But I just want to be clear that you are saying what I am reading,
> which is that I came to this language too late to really make a
> difference in it.

Depends on how you look at it.

Among languages of any note, I suspect D is one of the more open to language design discussions. Also, there is plenty of fun to be had with library enhancements, proving properties of language constructs, tightening the screws all around, writing articles, tutorials, and documentation, and more. We're just at the beginning of a vast expansion.

If by making a difference you mean strictly adding a language feature to D, you're not late even for that but you have to come up with something pretty darn interesting. Your proposal is not that; it does hold water, it is likely implementable, and it is possibly useful (though I have some doubts about the latter). It's just not compelling enough to make the A list, and we can't afford anything but the A+ list.

Note that most people tend to vastly overestimate their few first language designs, and that there are much more people who think are good at language design than those actually are. (Note I'm only passing opinion on what I saw; You may as well be an awesome language designer, but the spark is not visible in this particular proposal.) Though I've had an idea or two that stuck, I confess without any false modesty that I don't consider myself to be a noted language designer.


Andrei