www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Optional function invocation parentheses

reply "Will Rubin" <Will.Rubin zippymail.info> writes:
I'm new to D. While poking around the site I stumbled across 
Uniform Function Call Syntax. This lead me here: 
http://www.reddit.com/r/programming/comments/vvpfy/uniform_function_call_syntax_in_d_gamedevnet/c58f8yy

I seem to remember reading that empty function invocation parens 
were now optional so I tried it and it worked fine. But the 
comments in the above thread indicate that there is something 
special about removing them and it shouldn't be done so casually.

Are the following two "results" equivalent or is there something 
special going on behind the scenes that makes result2 less 
desirable?

import std.stdio;
import std.algorithm;

void main() {
   auto result1 = [1, 2, 3, 4].filter!(a => a < 4)().reduce!((a, 
b) => a + b)();
   writeln("Result1: ", result1);

   auto result2 = [1, 2, 3, 4].filter!(a => a < 4).reduce!((a, b) 
=> a + b);
   writeln("Result2: ", result2);
}
Sep 20 2012
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Thursday, September 20, 2012 09:40:53 Will Rubin wrote:
 I'm new to D. While poking around the site I stumbled across
 Uniform Function Call Syntax. This lead me here:
 http://www.reddit.com/r/programming/comments/vvpfy/uniform_function_call_syn
 tax_in_d_gamedevnet/c58f8yy
 
 I seem to remember reading that empty function invocation parens
 were now optional so I tried it and it worked fine. But the
 comments in the above thread indicate that there is something
 special about removing them and it shouldn't be done so casually.
 
 Are the following two "results" equivalent or is there something
 special going on behind the scenes that makes result2 less
 desirable?
 
 import std.stdio;
 import std.algorithm;
 
 void main() {
    auto result1 = [1, 2, 3, 4].filter!(a => a < 4)().reduce!((a,
 b) => a + b)();
    writeln("Result1: ", result1);
 
    auto result2 = [1, 2, 3, 4].filter!(a => a < 4).reduce!((a, b)
 => a + b);
    writeln("Result2: ", result2);
 }

Historically in D, you could leave out the parens on any function call which didn't take any arguments (originally due to a compiler bug IIRC, though people liked it enough that it stayed). That caused some problems with delegates and whatnot (e.g. if you returned a delegate from a function, it didn't get called with only one set of parens, even if you wanted to treat that function as a property function). property was introduced to solve this with the idea that any function marked with property would be used like a property (i.e. it was an abstraction for a variable and would be used like a variable - without parens) and functions without property would have to be called with parens. It was partially implemented and the -property flag was added to indicate that you wanted this enforced, but neither property or -property is really fully implemented, and you can still leave off the parens whenever you feel like it. When -property was introduced, it was with the idea that its implementation issues would be sorted out and then it would become the normal behavior. In part because of UFCS and templated functions where you pass a predicate but (like reduce), some people have expressed a dislike for the idea that they would be forced to use or not use parens based on property, so what exactly is going to happen in the long run is a bit up in the air at this point. My guess is that what's going to happen is that eventually, property functions will be forced to be called without parens (fixing the aforementioned problem with delegates) but that non- property functions will be able to use parens or not as you please, but I don't know. Personally, I think that it should always be enforced that property doesn't use parens and everything else does, but while plenty of people agree with me, plenty of others disagree. It's a very devisive subject. So, we'll just have to wait and see how it turns out. In the meantime however, you can use parens or not as you like. - Jonathan M Davis
Sep 20 2012
prev sibling next sibling parent "Will Rubin" <Will.Rubin zippymail.info> writes:
Thanks for the detailed reply. It's too early for me to have much 
of an opinion but I'll take your approach and use  Property 
without parens (as I would in C# for example) and stick with the 
empty parens for non-property functions as it's a bit clearer to 
see what's really going on at this right now.

A bit interesting to see I can declare a write property that 
returns a value rather than void.

On Thursday, 20 September 2012 at 07:56:09 UTC, Jonathan M Davis 
wrote:
 My guess is that what's going to happen is that eventually, 
  property
 functions will be forced to be called without parens (fixing 
 the aforementioned
 problem with delegates) but that non- property functions will 
 be able to use
 parens or not as you please, but I don't know. Personally, I 
 think that it
 should always be enforced that  property doesn't use parens and 
 everything
 else does, but while plenty of people agree with me, plenty of 
 others
 disagree.  It's a very devisive subject. So, we'll just have to 
 wait and see
 how it turns out.

 In the meantime however, you can use parens or not as you like.

Sep 20 2012
prev sibling next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Thursday, 20 September 2012 at 12:59:51 UTC, Will Rubin wrote:
 Thanks for the detailed reply. It's too early for me to have 
 much of an opinion but I'll take your approach and use 
  Property without parens (as I would in C# for example) and 
 stick with the empty parens for non-property functions as it's 
 a bit clearer to see what's really going on at this right now.

FYI, you can use the -d compile option to enforce the "proper" usage.
 A bit interesting to see I can declare a write property that 
 returns a value rather than void.

non void: auto a = someRange.front; front is a property that returns a value.
Sep 20 2012
prev sibling next sibling parent "Will Rubin" <Will.Rubin zippymail.info> writes:
Just a _write_ property:

struct Bleem {
   int _value;
public:
   // property int value() { return _value; }
    property int value(int newValue) { return _value = newValue; }
}

void main() {
   auto bleem = Bleem();
   writeln("Result: ", bleem.value = 9);
}

Application Output
Result: 9

Off the top of my head (C#, Delphi, Python) have them return 
void. Maybe it's not so uncommon though.

On Thursday, 20 September 2012 at 13:57:54 UTC, monarch_dodra 
wrote:
 A bit interesting to see I can declare a write property that 
 returns a value rather than void.

a non void: auto a = someRange.front; front is a property that returns a value.

Sep 20 2012
prev sibling next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Thursday, 20 September 2012 at 14:31:55 UTC, Will Rubin wrote:
 Just a _write_ property:

 struct Bleem {
   int _value;
 public:
   // property int value() { return _value; }
    property int value(int newValue) { return _value = newValue; 
 }
 }

 void main() {
   auto bleem = Bleem();
   writeln("Result: ", bleem.value = 9);
 }

 Application Output
 Result: 9

 Off the top of my head (C#, Delphi, Python) have them return 
 void. Maybe it's not so uncommon though.

 On Thursday, 20 September 2012 at 13:57:54 UTC, monarch_dodra 
 wrote:
 A bit interesting to see I can declare a write property that 
 returns a value rather than void.

a non void: auto a = someRange.front; front is a property that returns a value.


It is usually more common to just have a read property that returns a reference, which can be written to. If the property needs an explicit write version, then usually, returning a value is considered "costly". But the point is you can do whatever you want anyways.
Sep 20 2012
prev sibling next sibling parent "Jesse Phillips" <Jessekphillips+D gmail.com> writes:
On Thursday, 20 September 2012 at 13:57:54 UTC, monarch_dodra 
wrote:
 On Thursday, 20 September 2012 at 12:59:51 UTC, Will Rubin 
 wrote:
 Thanks for the detailed reply. It's too early for me to have 
 much of an opinion but I'll take your approach and use 
  Property without parens (as I would in C# for example) and 
 stick with the empty parens for non-property functions as it's 
 a bit clearer to see what's really going on at this right now.

FYI, you can use the -d compile option to enforce the "proper" usage.

What do you mean by this, -d allows deprecated features to be compiled in, wouldn't that be allowing "unproper" usage?
Sep 20 2012
prev sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Thursday, 20 September 2012 at 17:13:09 UTC, Jesse Phillips 
wrote:
 On Thursday, 20 September 2012 at 13:57:54 UTC, monarch_dodra 
 wrote:
 On Thursday, 20 September 2012 at 12:59:51 UTC, Will Rubin 
 wrote:
 Thanks for the detailed reply. It's too early for me to have 
 much of an opinion but I'll take your approach and use 
  Property without parens (as I would in C# for example) and 
 stick with the empty parens for non-property functions as 
 it's a bit clearer to see what's really going on at this 
 right now.

FYI, you can use the -d compile option to enforce the "proper" usage.

What do you mean by this, -d allows deprecated features to be compiled in, wouldn't that be allowing "unproper" usage?

Oops, I meant: -property enforce property syntax
Sep 20 2012