December 03, 2012
On 12/02/2012 09:19 PM, Regan Heath wrote:
> On Sun, 02 Dec 2012 18:47:26 -0000, Rob T <rob@ucora.com> wrote:
>> If someone can honestly demonstrate a non-subjective reason why there
>> must be a difference between function call and variable assignments,
>> please show it. So far I've only seen arguments that boil down to "I
>> don't like it".
>
> A variable assignment is in 99% of cases a simple operation.  A function
> call is in 99% of cases a more complex operation.  Being able to
> immediately "see" those costs is useful.  A language which allows you to
> make variable assignments costly will be inherently harder to understand
> in terms of cost, than a language which does not.
>
> R
>

Costs are understood by profiling and/or detailed analysis, not by looking at trivial syntactic properties.
December 03, 2012
On 12/02/2012 12:36 PM, Artur Skawina wrote:
> On 12/02/12 07:57, Jonathan M Davis wrote:
>> On Sunday, December 02, 2012 07:49:52 deadalnix wrote:
>>> And what do you think about map!(x => x * x) = generator(x, y, z)
>>> ?
>>
>> What's that even supposed to mean? map has been given no function argument
>> either as UFCS or with a normal function call, so it's not being called. And
>> even if it were, it wouldn't result in an lvalue, so putting it on the left of
>> an assignment makes no sense. I have no idea what you're trying to do here.
>
>     void main() {
>        import std.stdio;
>
>        writeln!string = "Hello World!";
>     }
>
>     // The explicit "!string" is only needed because of no IFTI, if 'writeln' was
>     // a function instead of a template you could just call it like "writeln = "blah".
>
> Allowing that /by default/ does much more harm than good,

It does neither harm nor good.

> proper property enforcement is necessary. Function calls go via '()'. Programmer can override
> when he knows better.

The first and last sentence are in mutual contradiction.

> UFCS doesn't change things. [1]
>
> artur
>
> [1] If you think the required '()' in UFCS chains look ugly, you're right, but the
> right fix isn't to butcher the language. '()' carry important information.

They do not, otherwise compilation could not succeed.

> Having a mode where function calls are made w/o the parens would be a good idea, but it
> should be limited to an explicit scope. ie something like
> "auto r = function {generator(x, y, z).map!(x => x * x)};", except 'function' keyword
> can't be overloaded like that, it's too long, and ()-less calls isn't the only change
> that could be done.
>

That is terrible.
December 03, 2012
On 12/03/12 05:10, Timon Gehr wrote:
> On 12/02/2012 12:36 PM, Artur Skawina wrote:
>> On 12/02/12 07:57, Jonathan M Davis wrote:
>>> On Sunday, December 02, 2012 07:49:52 deadalnix wrote:
>>>> And what do you think about map!(x => x * x) = generator(x, y, z)
>>>> ?
>>>
>>> What's that even supposed to mean? map has been given no function argument either as UFCS or with a normal function call, so it's not being called. And even if it were, it wouldn't result in an lvalue, so putting it on the left of an assignment makes no sense. I have no idea what you're trying to do here.
>>
>>     void main() {
>>        import std.stdio;
>>
>>        writeln!string = "Hello World!";
>>     }
>>
>>     // The explicit "!string" is only needed because of no IFTI, if 'writeln' was
>>     // a function instead of a template you could just call it like "writeln = "blah".
>>
>> Allowing that /by default/ does much more harm than good,
> 
> It does neither harm nor good.

As long as nobody is (ab)using it.

   int f(int a) { return sqrt = a; }

is not much different from abusing op overloading and is an equally bad idea.
It shouldn't be allowed by /default/, which not enforcing @property will lead to.
Somebody reading that 'f()' definition should be able to rely on sqrt being a
variable, possibly of a user defined type, even with an overloaded assignment
operator, which could have side effects. Assuming that the type designer made
sensible choices is relatively safe, assuming that every user will do the right
thing won't work.
What would be the rationale for allowing this syntax for calling every random
function? Other than not having to declare it as a @property when required.

>> proper property enforcement is necessary. Function calls go via '()'. Programmer can override when he knows better.
> 
> The first and last sentence are in mutual contradiction.

No, they are not, because enforcement is a requirement for control. And that has to be with the producer, not the consumer (ie determined by the function declaration, not individually at every call site).


>> [1] If you think the required '()' in UFCS chains look ugly, you're right, but the
>> right fix isn't to butcher the language. '()' carry important information.
> 
> They do not, otherwise compilation could not succeed.

not required != unimportant.

The compiler could for example in many cases figure out by itself that a missing (const) cast is necessary for some code to compile. That does not mean that it should insert them implicitly, w/o making sure doing so is both harmless and won't cause confusion.

>> Having a mode where function calls are made w/o the parens would be a good idea, but it
>> should be limited to an explicit scope. ie something like
>> "auto r = function {generator(x, y, z).map!(x => x * x)};", except 'function' keyword
>> can't be overloaded like that, it's too long, and ()-less calls isn't the only change
>> that could be done.
>>
> 
> That is terrible.

Yes, it *is* terrible - the point was that it can be done differently and this could be a start for discussion. That kind of semi-dsl also allows for locally lifting other restrictions like order of evaluation etc w/o butchering the rest of the language.

artur
December 03, 2012
> int func() { return 1; }
> void func(int n) { }
> @property int prop() { return 2; }
> @property void prop(int n) { }
> void main() {
>   // Without -property switch, all lines can compile.
>   // With -property switch:
>   func();     // OK -> OK
>   func(1);    // OK -> OK
>   func;       // OK -> OK [*]
>   func = 1;   // OK -> NG (fixed!)
>   prop();     // OK -> NG (fixed!)
>   prop(1);    // OK -> NG (fixed!)
>   prop;       // OK -> OK
>   prop = 1;   // OK -> OK
> }
>
DIP21: Fixing @property

Nice but DIP21 does not discuss dynamic D.


December 04, 2012
Isn't it possible to have parentheses optional only for UFCS?

E.g.

Allow:
I 5.writeln

Dissallow:

void f()
{
	writeln("hi");
}

f; // this currently works


I don't know if this is possible to implement.
December 04, 2012
On 04/12/2012 16:24, Minas Mina wrote:
> Isn't it possible to have parentheses optional only for UFCS?
>
> E.g.
>
> Allow:
> I 5.writeln
>
> Dissallow:
>
> void f()
> {
>      writeln("hi");
> }
>
> f; // this currently works
>
>
> I don't know if this is possible to implement.

I expect it is, perhaps by disallowing calling a property function with no arguments.
December 04, 2012
On Tuesday, 4 December 2012 at 16:24:27 UTC, Minas Mina wrote:
> Isn't it possible to have parentheses optional only for UFCS?
>
> E.g.
>
> Allow:
> I 5.writeln
>
> Dissallow:
>
> void f()
> {
> 	writeln("hi");
> }
>
> f; // this currently works
>
>
> I don't know if this is possible to implement.


module main;

void f()
{
	writeln("hi");
}

main.f; // OK or not?

If we're to make the empty braces optional, we have to ask this question: What will enforcing the empty braces buy you?

Based on the comments so far, all that it does is tell you at a glance that the symbol is a function call. Without the braces you'll have to dig a little deeper into the code to figure it out. So the () effectively serves the purpose of a naming convention for functions. However as was pointed out in this thread, there are a few real situations where even with () enforcement, you still won't necessarily know what the symbol represents without digging into the code, for example if @property is enforced. There are arguments in favor of @property enforcement, which is to encourage the programmer to think in terms of making a function behave like a variable and nothing else. It also discourages dropping the () elsewhere. The argument against @property enforcement, is that it enforces a coding style on the programmer, which may be subjective, and not providing any real gain.

What "bad" thing does () enforcement do?

Based the comments, it seems that a lot of people really dislike the empty braces when chaining together multiple function calls, i.e., it looks ugly and is more effort for apparently no real gain, so it does not matter if they are UFCS calls or not, it's just ugly when chaining. The arguments against dropping the () when chaining, is that you loose the ability to see at a glance what is a function call and what is not, although with the exception of enforced @property functions.

I think the above sums up the arguments for and against, but maybe not.

--rt
December 04, 2012
On Tuesday, 4 December 2012 at 16:24:27 UTC, Minas Mina wrote:
> Isn't it possible to have parentheses optional only for UFCS?
>

This is exactly what Nimrod does. ;-) The () can also be omitted in calls used as a statement (not as an expression).

BTW Nimrod calls it "method call syntax"; there is hardly anything "uniform" in having the first argument in a special position...
December 04, 2012
On Tuesday, 4 December 2012 at 16:24:27 UTC, Minas Mina wrote:
> Isn't it possible to have parentheses optional only for UFCS?
>
> E.g.
>
> Allow:
> I 5.writeln
>
> Dissallow:
>
> void f()
> {
> 	writeln("hi");
> }
>
> f; // this currently works
>
>
> I don't know if this is possible to implement.


module main;

void f()
{
	writeln("hi");
}

main.f; // OK or not?

I think the argument for vs against is simply a coding style issue, some like dropping empty braces, some do not.

--rt

December 04, 2012
On Tuesday, 4 December 2012 at 16:24:27 UTC, Minas Mina wrote:
> Isn't it possible to have parentheses optional only for UFCS?
>
> E.g.
>
> Allow:
> I 5.writeln
>
> Dissallow:
>
> void f()
> {
> 	writeln("hi");
> }
>
> f; // this currently works
>
>
> I don't know if this is possible to implement.


module main;

void f()
{
	writeln("hi");
}

main.f; // OK or not?

I think the argument for vs against is simply a coding style
issue, some like dropping empty braces, some do not.

--rt