February 05, 2013
On Tuesday, February 05, 2013 14:05:24 Steven Schveighoffer wrote:
> I think the point about @safe code is moot, aren't pointers disallowed in safe code anyway?

Goodness no. It's pointer arithmetic which is disallowed. Pointers themselves are perfectly safe as long as you just pass them around or dereference them (which would include calling functions on them). For instance, the result of in on an AA is a pointer to the object, and that's @safe.

- Jonathan M Davis
February 05, 2013
On Tue, 05 Feb 2013 15:15:05 -0500, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> On 2/5/13 2:05 PM, Steven Schveighoffer wrote:
>>
>> I think a cast would be sufficient:
>>
>> cast(int *)(&refparam); // understood that a cast is required
>>
>> To jump through this machinery to turn a reference into a, um...
>> reference, seems like a huge waste of code space and resources.
>
> The whole point was to avoid using operator &.

The mechanism to avoid it seems overly extravagant (and prone to low performance).  If you want actually avoid using operator &, then make a compiler special function or something.

Also, the use of & can still be hidden inside a function.

-Steve
February 05, 2013
On Tue, 05 Feb 2013 16:43:39 -0500, Jonathan M Davis <jmdavisProg@gmx.com> wrote:

> On Tuesday, February 05, 2013 14:05:24 Steven Schveighoffer wrote:
>> I think the point about @safe code is moot, aren't pointers disallowed in
>> safe code anyway?
>
> Goodness no. It's pointer arithmetic which is disallowed. Pointers themselves
> are perfectly safe as long as you just pass them around or dereference them
> (which would include calling functions on them). For instance, the result of
> in on an AA is a pointer to the object, and that's @safe.

Well, it would seem setting all kinds of extra rules on ref (in addition to the restrictions we have now), when pointers are more useful even in @safe code, will simply result in people using pointers more than ref.  I'm not sure that's the right message, but I'm afraid that will be what it is.

For example, I have to use pointers for my linked list implementation in dcollections, because ref is forbidden to be used as a class or struct member (my nodes are structs because classes are too heavy).  Also, ref is not rebindable, whereas a pointer is.

-Steve
February 05, 2013
On Tue, 05 Feb 2013 15:21:14 -0500, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> 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.

I look forward to reading it.

-Steve
February 05, 2013
On 2/5/13 4:35 PM, Zach the Mystic wrote:
> On Tuesday, 5 February 2013 at 20:24:16 UTC, Andrei Alexandrescu wrote:
>>> I hope it at least considers my proposal with regard to 'out' return
>>> values. 'out' implies ref and guarantees that the result is as good as
>>> global:
>>>
>>> out int foo(ref int a) { return a; } // Error, 'out' return may not
>>> return ref parameter
>>> out int goo(ref int a) { return new int; } // Fine
>>>
>>> My impression was that this would solve 98% of problems, the other 2%
>>> requiring scope parameters, which also imply ref:
>>>
>>> ref int haa(ref int a, scope int b) { return b; } // Error, may not
>>> return scope parameter
>>> ref int gaa(ref int a, scope int b) { return a; } // Fine
>>
>> I'm sorry, I didn't know of that proposal. Generally we're aiming for
>> economy of means i.e. we want to clarify semantics of existing syntax
>> instead of adding new syntax and semantics.
>>
>> Andrei
>
> It's not a new syntax, just new semantics. Also, the reason for adding
> these semantics to the function signature was so that the compiler would
> never have to leave the function in order to compile it. It's a natural
> complement to ref returns' scope being the most local of the ref
> parameters, which you suggested in your proposal. It keeps that too.

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
February 05, 2013
On Tuesday, February 05, 2013 08:31:46 Andrei Alexandrescu wrote:
> On 2/5/13 3:39 AM, Dmitry Olshansky wrote:
> > On 02/05/2013 02:28 AM, Andrei Alexandrescu wrote:> On 2/4/13 2:04 PM,
> > 
> > Jonathan M Davis wrote:
> >  >> We could save a lot of boilerplate code if we can simply make it
> >  >> variables and
> >  >> property functions guaranteed to be swappable without breaking code.
> >  >
> >  > I think this is quite powerful. The way we can do this is by making
> >  > properties emulate a subset of actual variables.
> > 
> > This is the primary real-world proble to solve.
> 
> The problem with this approach is feature creep - there will always be yet another possible case in which a feature helps some case. We need to put a halt on that.

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.

> 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.

- Jonathan M Davis
February 05, 2013
On 2/5/13 4:45 PM, Steven Schveighoffer wrote:
> On Tue, 05 Feb 2013 15:15:05 -0500, Andrei Alexandrescu
> <SeeWebsiteForEmail@erdani.org> wrote:
>
>> On 2/5/13 2:05 PM, Steven Schveighoffer wrote:
>>>
>>> I think a cast would be sufficient:
>>>
>>> cast(int *)(&refparam); // understood that a cast is required
>>>
>>> To jump through this machinery to turn a reference into a, um...
>>> reference, seems like a huge waste of code space and resources.
>>
>> The whole point was to avoid using operator &.
>
> The mechanism to avoid it seems overly extravagant (and prone to low
> performance). If you want actually avoid using operator &, then make a
> compiler special function or something.

As I said, there are various solutions. I wrote one that's reasonably portable.

> Also, the use of & can still be hidden inside a function.

My point was to not need & such that the function itself can be compiled.

Overall I think this is not the focal issue, the consequences are.


Andrei

February 05, 2013
On Tuesday, February 05, 2013 16:53:51 Steven Schveighoffer wrote:
> On Tue, 05 Feb 2013 16:43:39 -0500, Jonathan M Davis <jmdavisProg@gmx.com>
> 
> wrote:
> > On Tuesday, February 05, 2013 14:05:24 Steven Schveighoffer wrote:
> >> I think the point about @safe code is moot, aren't pointers disallowed
> >> in
> >> safe code anyway?
> > 
> > Goodness no. It's pointer arithmetic which is disallowed. Pointers
> > themselves
> > are perfectly safe as long as you just pass them around or dereference
> > them
> > (which would include calling functions on them). For instance, the
> > result of
> > in on an AA is a pointer to the object, and that's @safe.
> 
> Well, it would seem setting all kinds of extra rules on ref (in addition to the restrictions we have now), when pointers are more useful even in @safe code, will simply result in people using pointers more than ref. I'm not sure that's the right message, but I'm afraid that will be what it is.
> 
> For example, I have to use pointers for my linked list implementation in dcollections, because ref is forbidden to be used as a class or struct member (my nodes are structs because classes are too heavy).  Also, ref is not rebindable, whereas a pointer is.

That may end up happening, but the issues with ref may boil over into some of what happens with pointers - the key issue being escaping references. Using & on a local variable is already considered unsafe, but using ref as a function parameter gets you pretty much exactly the same thing if a local variable is passed to it and ref is returned by the function (I believe that discussions on that are what triggered Andrei's work on the DIP on ref that he brought up). What's really needed is to be able to detect and prevent escaping pointers and references, and there are a lot of difficulties with that. The easy way out tends to mean making a lot of code be @system, which could either end up being very limiting or result in a lot more code being @system instead of @safe. I don't know what exactly Andrei and Walter are cooking up, but SafeD could end up becoming very limited with regards to pointers and refs in order to deal with all of the corner cases.

- Jonathan M Davis
February 05, 2013
On 02/05/2013 09:15 PM, Andrei Alexandrescu wrote:
> ...
> The whole point was to avoid using operator &.
> ...

Well, that is completely unnecessary.
February 05, 2013
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)