January 24, 2013
On 01/24/2013 10:24 PM, Adam Wilson wrote:
> ...
>
> All I can say is that in this case even with UFCS C# enforces parens
> because it's syntactically clear. Yes, it might be slightly annoying to
> have to type the (), but that's how you define a function in every other
> language. A shortcut with side-effects isn't a short-cut, it's a bug
> factory.

It is not a shortcut, it is a formatting option, and using it does not have side effects.

> And to be honest, once the language spec settles down tools
> like ReSharper/VisualAssist/etc. can take care of the extra parens.

Tools will be configurable to highlight certain constructs anyway.

> I hand type a small fraction of the parens that actually appear in my C#
> code.
>

It is about reading, not typing.


January 24, 2013
On Thu, 24 Jan 2013 00:34:42 -0800, Walter Bright <newshound2@digitalmars.com> wrote:

> This has turned into a monster. We've taken 2 or 3 wrong turns somewhere.
>
> Perhaps we should revert to a simple set of rules.
>
> 1. Empty parens are optional. If there is an ambiguity with the return value taking (), the () go on the return value.
>
> 2. the:
>     f = g
> rewrite to:
>     f(g)
> only happens if f is a function that only has overloads for () and (one argument). No variadics.
>
> 3. Parens are required for calling delegates or function pointers.
>
> 4. No more @property.

I want to point out another usage of properties that invades my work every day. Consider:

public partial class CustomerXAML : DependencyObject
{
	public Guid ID { get { return (Guid)GetValue(IDProperty); }  set { SetValue(IDProperty, value); } }
	public static readonly DependencyProperty IDProperty = DependencyProperty.Register("ID", typeof(Guid), typeof(CustomerXAML), null);
}

Where:

public class DependencyObject
{
	public object GetValue(DependencyProperty prop);
	public void SetValue(DependencyProperty prop, object value);
}

What does this code say? I am dealing with data or calling a function? Well to those of you not familiar with WPF/XAML's Dependency pattern let me explain. You're doing both.

You see XAML uses something that for lack of a better term I will call a "sparse memory model". Another way to describe it is to say that the DependencyObject stores ONLY the values that have been changed from the default value. They had to do this because their object model is ridiculous and they needed over a gigabyte of RAM just to instantiate all the objects required to draw an empty window. They discovered that most of the values in the object didn't change from the defaults.

However, the changes had to be stored in a Dictionary (think Map) for speed, that's what all the typeof's in the Register function are for. And storing/retrieving those directly from the Map would have lead to all sorts of problems. So GetValue/SetValue handle that for you and allows them to do much more, like databinding and update callbacks.

My point is this. This does not violate encapsulation, we ARE working with just DATA, but we want to hide the implementation details of HOW we are working with said data, and in this case we CANNOT use a simple backing field. From a user perspective CustomerXAML.ID is JUST data FIELD. But behind the scenes it's a bit more complicated than that.

THAT is the power of properties.

-- 
Adam Wilson
IRC: LightBender
Project Coordinator
The Horizon Project
http://www.thehorizonproject.org/
January 24, 2013
On Thu, 24 Jan 2013 15:04:20 -0800, Timon Gehr <timon.gehr@gmx.ch> wrote:

> On 01/24/2013 10:24 PM, Adam Wilson wrote:
>> ...
>>
>> All I can say is that in this case even with UFCS C# enforces parens
>> because it's syntactically clear. Yes, it might be slightly annoying to
>> have to type the (), but that's how you define a function in every other
>> language. A shortcut with side-effects isn't a short-cut, it's a bug
>> factory.
>
> It is not a shortcut, it is a formatting option, and using it does not have side effects.
>
>> And to be honest, once the language spec settles down tools
>> like ReSharper/VisualAssist/etc. can take care of the extra parens.
>
> Tools will be configurable to highlight certain constructs anyway.
>
>> I hand type a small fraction of the parens that actually appear in my C#
>> code.
>>
>
> It is about reading, not typing.
>
>

*sigh* ideally yes, it's just a formating option. The problem is that right now, it's NOT.

Consider:

module main;

import std.stdio;

struct Thing {
	int foo() { return 0; } // method
	int bar; // data field
	@property int baz() { return 0; } // data field
}

int main(string[] argv)
{
	writeln("Hello D-World!");
	return 0;
	Thing t;
	t.bar = 10; // this is a data field because it is
	// declared as "int bar" above,
	// not because I didn't use parens down here

	t.foo; // this is a function call because t.foo is a function

	t.baz; // this is a data field because i declared
	// "@property int" above, not because I left off parens here

	t.bar(); // error, type int has no call method

	t.baz(); // is this a function or a property? oops have to go look at the code.
}

But what happens if t.baz returns a delegate?

Because properties, which conceptually have nothing to do with functions, are implemented as functions they have the same optional parens rules as functions. The problem is that they aren't intended to be used as functions so in the case of delegate, you get massive explosions in the compiler. For something that should be straight-forward. If t.baz is a delegate than t.baz() should call the DELEGATE, but it doesn't...

Optional Parens Encourage Ambiguity. Ambiguity Fosters Bugs.

-- 
Adam Wilson
IRC: LightBender
Project Coordinator
The Horizon Project
http://www.thehorizonproject.org/
January 24, 2013
On Thu, 24 Jan 2013 00:34:42 -0800, Walter Bright <newshound2@digitalmars.com> wrote:

> This has turned into a monster. We've taken 2 or 3 wrong turns somewhere.
>
> Perhaps we should revert to a simple set of rules.
>
> 1. Empty parens are optional. If there is an ambiguity with the return value taking (), the () go on the return value.
>
> 2. the:
>     f = g
> rewrite to:
>     f(g)
> only happens if f is a function that only has overloads for () and (one argument). No variadics.
>
> 3. Parens are required for calling delegates or function pointers.
>
> 4. No more @property.

I just worked through this with Alexander Bothe (of Mono-D fame). Here is what C# does.

public Action temp { get; set; }
public Action Event { get { return temp; } }
t.Event; //returns the delegate
t.Event(); //calls the delegate.

Simple, clean, clear, concise. No problems with optional parens.

(Action is a delegate in C#)

-- 
Adam Wilson
IRC: LightBender
Project Coordinator
The Horizon Project
http://www.thehorizonproject.org/
January 25, 2013
On 1/24/13 6:52 PM, Adam Wilson wrote:
> On Thu, 24 Jan 2013 00:34:42 -0800, Walter Bright
> <newshound2@digitalmars.com> wrote:
>
>> This has turned into a monster. We've taken 2 or 3 wrong turns somewhere.
>>
>> Perhaps we should revert to a simple set of rules.
>>
>> 1. Empty parens are optional. If there is an ambiguity with the return
>> value taking (), the () go on the return value.
>>
>> 2. the:
>> f = g
>> rewrite to:
>> f(g)
>> only happens if f is a function that only has overloads for () and
>> (one argument). No variadics.
>>
>> 3. Parens are required for calling delegates or function pointers.
>>
>> 4. No more @property.
>
> I just worked through this with Alexander Bothe (of Mono-D fame). Here
> is what C# does.
>
> public Action temp { get; set; }
> public Action Event { get { return temp; } }
> t.Event; //returns the delegate
> t.Event(); //calls the delegate.
>
> Simple, clean, clear, concise. No problems with optional parens.
>
> (Action is a delegate in C#)

This looks essentially the same as Walter's proposal.

Andrei
January 25, 2013
On Thursday, 24 January 2013 at 22:04:02 UTC, Andrei Alexandrescu wrote:
[..]
>
> There's been a lot of strong positions years ago about functions vs. procedures, statements vs. expressions, or even (the glorious 60s!) in-language I/O primitives vs. I/O as library facilities. Successful languages managed to obviate such dichotomies.
>
>
> Andrei

Yeah, back in the day it was a relief to no longer have to decide if I needed to write a function or if I needed to write a procedure. With D, it's been a relief to no longer have to use empty () everywhere.

I think we've become stuck in a way of thinking that is creating a lot more complexity than is actually required.

For example, I can change my perception of what a variable is and instead view it to be specialized form of function. It has a default implementation and implied storage, which is returned by ref. The compiler can optimize away the need to a real function call.

If you take on a view like that, then it may be possible to simplify the language by merging specialized types with alternate syntax into one generalized type with identical syntax. You'll also be forced to implement things in a more consistent and unambiguous way as you proceed along. For example, there has to be different methods for getting the address of the data vs the address of the implementation, and the same solution can work for all types provided that they are treated in the same way.

--rt
January 25, 2013
On 01/25/2013 01:12 AM, Andrei Alexandrescu wrote:
> On 1/24/13 6:52 PM, Adam Wilson wrote:
>> On Thu, 24 Jan 2013 00:34:42 -0800, Walter Bright
>> <newshound2@digitalmars.com> wrote:
>>
>>> This has turned into a monster. We've taken 2 or 3 wrong turns
>>> somewhere.
>>>
>>> Perhaps we should revert to a simple set of rules.
>>>
>>> 1. Empty parens are optional. If there is an ambiguity with the return
>>> value taking (), the () go on the return value.
>>>
>>> 2. the:
>>> f = g
>>> rewrite to:
>>> f(g)
>>> only happens if f is a function that only has overloads for () and
>>> (one argument). No variadics.
>>>
>>> 3. Parens are required for calling delegates or function pointers.
>>>
>>> 4. No more @property.
>>
>> I just worked through this with Alexander Bothe (of Mono-D fame). Here
>> is what C# does.
>>
>> public Action temp { get; set; }
>> public Action Event { get { return temp; } }
>> t.Event; //returns the delegate
>> t.Event(); //calls the delegate.
>>
>> Simple, clean, clear, concise. No problems with optional parens.
>>
>> (Action is a delegate in C#)
>
> This looks essentially the same as Walter's proposal.
>
> Andrei

Not at all. Walter's proposal just chooses the other option when stuff is "ambiguous" and adds a hideous special rule in case the empty argument list was obtained from an empty sequence.
January 25, 2013
On Thursday, 24 January 2013 at 08:35:01 UTC, Walter Bright wrote:
> 1. Empty parens are optional. If there is an ambiguity with the return value taking (), the () go on the return value.

As mentioned, this seems dangerous. I'd suggest requiring when there is ambiguity. It still has generic problems, but it will never be silent.

> 4. No more @property.

I'm on the side that would miss optional parens if they died. In would be nice if @property actually made a function behave like a field.

foo += bar;

It seems there are lots of complications around this? So yes kill @property.

On another note,

To properly correct this situation we will break code. So before you get started be sure to try out the new feature preview release approach :)
January 25, 2013
On Thu, 24 Jan 2013 16:29:24 -0800, Timon Gehr <timon.gehr@gmx.ch> wrote:

> On 01/25/2013 01:12 AM, Andrei Alexandrescu wrote:
>> On 1/24/13 6:52 PM, Adam Wilson wrote:
>>> On Thu, 24 Jan 2013 00:34:42 -0800, Walter Bright
>>> <newshound2@digitalmars.com> wrote:
>>>
>>>> This has turned into a monster. We've taken 2 or 3 wrong turns
>>>> somewhere.
>>>>
>>>> Perhaps we should revert to a simple set of rules.
>>>>
>>>> 1. Empty parens are optional. If there is an ambiguity with the return
>>>> value taking (), the () go on the return value.
>>>>
>>>> 2. the:
>>>> f = g
>>>> rewrite to:
>>>> f(g)
>>>> only happens if f is a function that only has overloads for () and
>>>> (one argument). No variadics.
>>>>
>>>> 3. Parens are required for calling delegates or function pointers.
>>>>
>>>> 4. No more @property.
>>>
>>> I just worked through this with Alexander Bothe (of Mono-D fame). Here
>>> is what C# does.
>>>
>>> public Action temp { get; set; }
>>> public Action Event { get { return temp; } }
>>> t.Event; //returns the delegate
>>> t.Event(); //calls the delegate.
>>>
>>> Simple, clean, clear, concise. No problems with optional parens.
>>>
>>> (Action is a delegate in C#)
>>
>> This looks essentially the same as Walter's proposal.
>>
>> Andrei
>
> Not at all. Walter's proposal just chooses the other option when stuff is "ambiguous" and adds a hideous special rule in case the empty argument list was obtained from an empty sequence.

Basically this. I was writing a longer post that essentially said this.

Also non-logical special case rules like this make the language harder to learn, therefore harder to evangelize.

-- 
Adam Wilson
IRC: LightBender
Project Coordinator
The Horizon Project
http://www.thehorizonproject.org/
January 25, 2013
2013/1/25 Jonathan M Davis <jmdavisProg@gmx.com>

> On Thursday, January 24, 2013 22:24:58 Adam D. Ruppe wrote:
> > On Thursday, 24 January 2013 at 21:09:39 UTC, Adam Wilson wrote:
> > > The problem with @property isn't @property, it's D's insistence on optional parens.
> >
> > No, this isn't a problem; function call syntax has nothing whatsoever to do with @property because a property is NOT logically a function!
>
> D's insistance on optional parens _does_ cause problems with functions that return delegates, but @property itself isn't really affected by optional parens save for the visual ambiguity caused by optional parens.


I think that the "optional parentheses" feature for normal functions should always work in _shallowly_. Even if a function returns some callable object, "optional parentheses" should not applied to the return object recursively.

That means:
void delegate() foo() { ... }
void main() {
  auto x = foo();  // typeof(x) == void delegate()
  auto y = foo;    // typeof(y) == void delegate()
}

Kenji Hara