September 29, 2008
Bill Baxter wrote:
> On Tue, Sep 30, 2008 at 3:36 AM, Steven Schveighoffer
> <schveiguy@yahoo.com> wrote:
>>> There is no ambiguity either case. You evaluate Stdout.newline. The
>>> evaluation yields a value of some type. Then you evaluate formatln against
>>> that value.
>> OK, then tell me what this does:
>>
>> x.y.z();
>>
>> Is y a property/field of x or a function call with no args?  I see a benefit
>> to being able to understand a line of code without requiring lots of extra
>> context.  I have to do less lookups of the source of a function or property.
> 
> The problem with this argument is that unless you disallow properties
> altogether, you still won't know whether y is actually a field or a
> call to a property method without looking it up.
> 
> --bb

I think the distinction of with and without () is pretty stylistic, because the same argument can even be applied to operator overloading (does a=b means pointing the variable a to b, or calling a.opAssign(b)?)

For me, I would use () if the function do modify the object itself.

September 29, 2008
Steven Schveighoffer wrote:
> "Andrei Alexandrescu" wrote
>> Steven Schveighoffer wrote:
>>> "Andrei Alexandrescu" wrote
>>>> Steven Schveighoffer wrote:
>>>>> "Andrei Alexandrescu" wrote
>>>>>> Steven Schveighoffer wrote:
>>>>>>> "Andrei Alexandrescu" wrote
>>>>>>>>> P.S. If src.next() is too lengthy, why not just adopt ++src?
>>>>>>>> Because people (in wake of the recently introduced array operations) may legitimately expect that to mean "increment all elements of src".
>>>>>>> So in one case, you believe people's assumptions aren't important, i.e. an assumption that .next without parens will not change anything on the object, yet in another case you believe people's assumptions are the main argument. This doesn't sound consistent.
>>>>>> Of course it is. One expectation has to do with operational consistency (albeit a tad far-fetched), the other has to do with being used to a mistaken decision in the C language design.
>>>>> You are assuming that the C language decision to require parentheses for all functions was a design mistake.  I would argue that the design was on purpose and correctly served that purpose.  The purpose was to remove ambiguity when faced with understanding code without all the context.
>>>> I have stated my assumption and its basis.
>>> Forgive me, but I must have missed it.  I saw only your assumption (or supposition) that the C designers made a mistake.
>> My post on 25 Sep 2008 17:58:52 -0500 mentions:
>>
>> "One principle that I consider universal is that a language should minimize the number of syntactic constructs that are semantically and/or pragmatically meaningless. Another that I also consider universal is that the more frequently-used constructs should be given syntactic priority over the less-used constructs, particularly when the latter are also at risk of breaking the first principle."
> 
> Hidden in this statement is that you consider () to be semantically meaningless.  I see it not as meaningless, but a distinction between what the symbol is supposed to represent.  A property should represent a value. A function should represent an action.

Sheesh, do I really need to spoonfeed all of this? First I mentioned the principles I quoted above. Then I clearly explained how C's handling of function names breaks these principle, with examples. Please refer to that post. There is nothing hidden my statement.

> I'll also note that your basis/proof is not any more proof than mine ;)  You just made statements about what you believe, as did I.

The note is wrong. I provide the principles as basis. Then I provide proof using that basis. If you want to invalidate that, you need to invalidate my basis, i.e., the principles of language design I am invoking. You are of course free to do that since principles of programming language design are to large extent a subjective matter.

>>>> What is the basis of yours?
>>> I don't have any actual proof that they did this on purpose, I wasn't working at Bell labs when C was invented, in fact, I don't even think I was born ;)
>>>
>>> But it makes logical sense, and still does.  If you want to call a function, you have to use parentheses.  If you want to access the function address, no parentheses.
>> This is no logic. Your proof is just stating the conclusion. It's a logical fallacy called proof by assertion.
> 
> Sorry, change my statement to 'But it makes sense and still does'.  And I never said it was a proof.  It's a statement of my reasons behind believing the () decision was on purpose.

The decision was on purpose, I am sure it wasn't an oversight. It was a poor decision because it breaks the aforementioned principles.

>>> It follows other design decisions they made:
>>>
>>> pointers:  Access what it's pointing to, use ->, get address it's pointing to, use symbol alone.
>> This is wrong too. If you use symbol alone, you are not getting its address. You are referring the pointer, which is an address. It would have been consistent with other design decisions if referring a variable alone would take its address.
> 
> Not really.  A function symbol by itself is the address of the function.  A pointer symbol by itself is the address of the data it points to.  It's the same.  I don't think you understood the detail that I stated, 'get address it's pointing to', not 'get address of the pointer'.

I understood very well. Your point is off by a mile, and getting only farther. Please understand how you are making an elementary mistake.

Consider:

int x;

Then if I only use "x", I am getting x's value (an lvalue in fact), not its address. Now consider:

int * x;

Then if I only use "x", I am getting x's value, which is the address of an int.

In neither case is it possible for x and &x to mean the same thing. For functions some really weird stuff happens:

// this is C
#include <assert.h>
void foo() {}

int main()
{
    void (*p1)() = foo;
    void (*p2)() = &foo;
    assert(p1 == p2);
}

So in fact accessing the name of the function and applying the address-of operator to it yield the same thing. That does not happen to pointers and anything else. Accessing any other symbol yields its value, not its address. I hope that clarifies things.

Before anyone will point that out, I'll hurry to mention C does have one other instance in which a symbol "decays" to an address: names f fixed-sized arrays decay to the address of their first element. Still for them the address-of operator is not idempotent, and the decision to allow said decaying has good justification given by subtyping.


Andrei
September 29, 2008
KennyTM~ wrote:
> Bill Baxter wrote:
>> On Tue, Sep 30, 2008 at 3:36 AM, Steven Schveighoffer
>> <schveiguy@yahoo.com> wrote:
>>>> There is no ambiguity either case. You evaluate Stdout.newline. The
>>>> evaluation yields a value of some type. Then you evaluate formatln against
>>>> that value.
>>> OK, then tell me what this does:
>>>
>>> x.y.z();
>>>
>>> Is y a property/field of x or a function call with no args?  I see a benefit
>>> to being able to understand a line of code without requiring lots of extra
>>> context.  I have to do less lookups of the source of a function or property.
>>
>> The problem with this argument is that unless you disallow properties
>> altogether, you still won't know whether y is actually a field or a
>> call to a property method without looking it up.
>>
>> --bb
> 
> I think the distinction of with and without () is pretty stylistic, because the same argument can even be applied to operator overloading (does a=b means pointing the variable a to b, or calling a.opAssign(b)?)
> 
> For me, I would use () if the function do modify the object itself.

But range.next does modify the object. On what basis do I need to add the trailing parens?

Andrei
September 29, 2008
On Tue, Sep 30, 2008 at 4:08 AM, KennyTM~ <kennytm@gmail.com> wrote:
> Bill Baxter wrote:
>>
>> On Tue, Sep 30, 2008 at 3:36 AM, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
>>>>
>>>> There is no ambiguity either case. You evaluate Stdout.newline. The
>>>> evaluation yields a value of some type. Then you evaluate formatln
>>>> against
>>>> that value.
>>>
>>> OK, then tell me what this does:
>>>
>>> x.y.z();
>>>
>>> Is y a property/field of x or a function call with no args?  I see a
>>> benefit
>>> to being able to understand a line of code without requiring lots of
>>> extra
>>> context.  I have to do less lookups of the source of a function or
>>> property.
>>
>> The problem with this argument is that unless you disallow properties altogether, you still won't know whether y is actually a field or a call to a property method without looking it up.
>>
>> --bb
>
> I think the distinction of with and without () is pretty stylistic, because
> the same argument can even be applied to operator overloading (does a=b
> means pointing the variable a to b, or calling a.opAssign(b)?)
>
> For me, I would use () if the function do modify the object itself.

I think the counter-argument to what I just said is that if properties had to be declared explicitly then at least we would know that .y is either a field or else something the designer *intended* to behave like a property.  Which does tell us something.  It most likely means that it's not an extremely heavy-weight operation, just a lightweight accessor with maybe a little logic on top.  That could be wrong, but in that case it's the class designer's fault for misleading us.

--bb
September 29, 2008
"Bill Baxter" wrote
> On Tue, Sep 30, 2008 at 3:36 AM, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
>>> There is no ambiguity either case. You evaluate Stdout.newline. The
>>> evaluation yields a value of some type. Then you evaluate formatln
>>> against
>>> that value.
>>
>> OK, then tell me what this does:
>>
>> x.y.z();
>>
>> Is y a property/field of x or a function call with no args?  I see a
>> benefit
>> to being able to understand a line of code without requiring lots of
>> extra
>> context.  I have to do less lookups of the source of a function or
>> property.
>
> The problem with this argument is that unless you disallow properties altogether, you still won't know whether y is actually a field or a call to a property method without looking it up.

Yes, but that is not in question.  A property method is *meant* to be used like a field, and so it shouldn't matter whether y is a property or field, it should be interchangable.

But if y is not meant to be a property, then it is confusing to read x.y.z() and realize that y isn't meant to be used as a property, and might not even do what you are expecting.

See the TimeSpan problem that I went through for an example:

http://www.dsource.org/projects/tango/ticket/1184

This problem would never occur if you could not just call any function as a property.

-Steve


September 29, 2008
Andrei Alexandrescu wrote:
> KennyTM~ wrote:
>> Bill Baxter wrote:
>>> On Tue, Sep 30, 2008 at 3:36 AM, Steven Schveighoffer
>>> <schveiguy@yahoo.com> wrote:
>>>>> There is no ambiguity either case. You evaluate Stdout.newline. The
>>>>> evaluation yields a value of some type. Then you evaluate formatln against
>>>>> that value.
>>>> OK, then tell me what this does:
>>>>
>>>> x.y.z();
>>>>
>>>> Is y a property/field of x or a function call with no args?  I see a benefit
>>>> to being able to understand a line of code without requiring lots of extra
>>>> context.  I have to do less lookups of the source of a function or property.
>>>
>>> The problem with this argument is that unless you disallow properties
>>> altogether, you still won't know whether y is actually a field or a
>>> call to a property method without looking it up.
>>>
>>> --bb
>>
>> I think the distinction of with and without () is pretty stylistic, because the same argument can even be applied to operator overloading (does a=b means pointing the variable a to b, or calling a.opAssign(b)?)
>>
>> For me, I would use () if the function do modify the object itself.
> 
> But range.next does modify the object. On what basis do I need to add the trailing parens?
> 
> Andrei

Well that's why *I* would use range.next() ;)
September 29, 2008
"Andrei Alexandrescu" wrote
> Steven Schveighoffer wrote:
>> Hidden in this statement is that you consider () to be semantically meaningless.  I see it not as meaningless, but a distinction between what the symbol is supposed to represent.  A property should represent a value. A function should represent an action.
>
> Sheesh, do I really need to spoonfeed all of this? First I mentioned the principles I quoted above. Then I clearly explained how C's handling of function names breaks these principle, with examples. Please refer to that post. There is nothing hidden my statement.

Sorry, I look at things more simply, and I'm not really into language design theory ;)  I didn't realize that calling something a principle meant that it is generally accepted to be fact, my apologies.

So I should read your statement as:

"a principle that is generally accepted to be universally true by major language design geeks, that I also agree with, is..."

I'm not trying to be clever here, I really didn't understand that it was implied.

So I agree with your principle, just not that () falls within the category of 'pragmatically or semantically meaningless.'

I'd also disagree that the most frequently used construct of calling a function is without parentheses.

>> I'll also note that your basis/proof is not any more proof than mine ;) You just made statements about what you believe, as did I.
>
> The note is wrong. I provide the principles as basis. Then I provide proof using that basis. If you want to invalidate that, you need to invalidate my basis, i.e., the principles of language design I am invoking. You are of course free to do that since principles of programming language design are to large extent a subjective matter.

Not really.  You provided no proof that your principles apply to this debate, you just stated that they do.

>> Sorry, change my statement to 'But it makes sense and still does'.  And I never said it was a proof.  It's a statement of my reasons behind believing the () decision was on purpose.
>
> The decision was on purpose, I am sure it wasn't an oversight. It was a poor decision because it breaks the aforementioned principles.

Respectfully disagree.

>> Not really.  A function symbol by itself is the address of the function. A pointer symbol by itself is the address of the data it points to.  It's the same.  I don't think you understood the detail that I stated, 'get address it's pointing to', not 'get address of the pointer'.
>
> I understood very well. Your point is off by a mile, and getting only farther. Please understand how you are making an elementary mistake.
>
> Consider:
>
> int x;
>
> Then if I only use "x", I am getting x's value (an lvalue in fact), not its address. Now consider:
>
> int * x;
>
> Then if I only use "x", I am getting x's value, which is the address of an int.
>
> In neither case is it possible for x and &x to mean the same thing. For functions some really weird stuff happens:
>
> // this is C
> #include <assert.h>
> void foo() {}

How does this make any difference to whether you can call a function without parentheses or not?  You are arguing that for a function defined as foo(), foo; should mean call function foo, and I'm arguing that it should be a syntax error.  Neither of us want the C behavior of evaluating to the function address.

I think &foo should be the proper method of taking the address of a function, as it is in D.

-Steve


September 29, 2008
"Steven Schveighoffer" wrote
> "Andrei Alexandrescu" wrote
>>> Not really.  A function symbol by itself is the address of the function. A pointer symbol by itself is the address of the data it points to. It's the same.  I don't think you understood the detail that I stated, 'get address it's pointing to', not 'get address of the pointer'.
>>
>> I understood very well. Your point is off by a mile, and getting only farther. Please understand how you are making an elementary mistake.
>>
>> Consider:
>>
>> int x;
>>
>> Then if I only use "x", I am getting x's value (an lvalue in fact), not its address. Now consider:
>>
>> int * x;
>>
>> Then if I only use "x", I am getting x's value, which is the address of an int.
>>
>> In neither case is it possible for x and &x to mean the same thing. For functions some really weird stuff happens:
>>
>> // this is C
>> #include <assert.h>
>> void foo() {}
>
> How does this make any difference to whether you can call a function without parentheses or not?  You are arguing that for a function defined as foo(), foo; should mean call function foo, and I'm arguing that it should be a syntax error.  Neither of us want the C behavior of evaluating to the function address.
>
> I think &foo should be the proper method of taking the address of a function, as it is in D.

This is what happens when you can't explain yourself correctly.  Stop typing your vehement response about how I am an idiot right now :)  I realize my mistake in the statements above.

I think the problem you cited with how foo is equivalent to &foo in C is bad.  I think we are getting sidetracked here, though.  The point I really want to state is that foo; shouldn't mean calling a function named foo.  I don't think it should mean the address of the function, although it seems consistent with C pointers (IMO, it seems like &foo shouldn't even compile in C if foo means 'address of foo' already).  &foo sounds correct to me, "address of foo."

Bottom line, I'm not defending the way C takes addresses of functions, but I think the requirement C has to use parentheses to call functions helps to clarify the intentions of the function author, and makes the code clearer.

-Steve


September 29, 2008
Steven Schveighoffer wrote:
> "Andrei Alexandrescu" wrote
>> Steven Schveighoffer wrote:
>>> Hidden in this statement is that you consider () to be semantically meaningless.  I see it not as meaningless, but a distinction between what the symbol is supposed to represent.  A property should represent a value. A function should represent an action.
>> Sheesh, do I really need to spoonfeed all of this? First I mentioned the principles I quoted above. Then I clearly explained how C's handling of function names breaks these principle, with examples. Please refer to that post. There is nothing hidden my statement.
> 
> Sorry, I look at things more simply, and I'm not really into language design theory ;)  I didn't realize that calling something a principle meant that it is generally accepted to be fact, my apologies.
> 
> So I should read your statement as:
> 
> "a principle that is generally accepted to be universally true by major language design geeks, that I also agree with, is..."
> 
> I'm not trying to be clever here, I really didn't understand that it was implied.

No, you shouldn't read it that way. (Explanation below.)

> So I agree with your principle, just not that () falls within the category of 'pragmatically or semantically meaningless.'

I'd also disagree with that, and I never said that either. What I said was that in C use of a function name alone is syntactically valid, semantically a no-op, and consequently pragmatically meaningless.

> I'd also disagree that the most frequently used construct of calling a function is without parentheses.

I'd also disagree with that, and I never said that either. My perception is that there is a serious "barrier in miscommunication" out there. What I said was that the most frequent use of a function is to call it. Therefore it is a pity that mentioning its name not only does not call it, but in fact does nothing.

>>> I'll also note that your basis/proof is not any more proof than mine ;) You just made statements about what you believe, as did I.
>> The note is wrong. I provide the principles as basis. Then I provide proof using that basis. If you want to invalidate that, you need to invalidate my basis, i.e., the principles of language design I am invoking. You are of course free to do that since principles of programming language design are to large extent a subjective matter.
> 
> Not really.  You provided no proof that your principles apply to this debate, you just stated that they do.

No, you don't understand. Let me explain again.

I stated two principles of language design. They could be true or false. They are up there for debate. They are subjective, because aside from some basics, language design is subjective.

The principles are:

1) A language should minimize the number of syntactic constructs that are semantically and/or pragmatically meaningless.

2) The more frequently-used constructs should be given syntactic priority over the less-used constructs, particularly when the latter are also at risk of breaking the first principle.

Then based on the principles I explained how C's use of function names breaks them in the post on Thu, 25 Sep 2008 22:59:04 +0000 (UTC). It's easy, really.

>>> Sorry, change my statement to 'But it makes sense and still does'.  And I never said it was a proof.  It's a statement of my reasons behind believing the () decision was on purpose.
>> The decision was on purpose, I am sure it wasn't an oversight. It was a poor decision because it breaks the aforementioned principles.
> 
> Respectfully disagree.

Now you either disagree with the principles, the consequences, or the way the consequences derive from the principles. My understanding is that the problem is with the latter. Again I am referring you to that same post.

>>> Not really.  A function symbol by itself is the address of the function. A pointer symbol by itself is the address of the data it points to.  It's the same.  I don't think you understood the detail that I stated, 'get address it's pointing to', not 'get address of the pointer'.
>> I understood very well. Your point is off by a mile, and getting only farther. Please understand how you are making an elementary mistake.
>>
>> Consider:
>>
>> int x;
>>
>> Then if I only use "x", I am getting x's value (an lvalue in fact), not its address. Now consider:
>>
>> int * x;
>>
>> Then if I only use "x", I am getting x's value, which is the address of an int.
>>
>> In neither case is it possible for x and &x to mean the same thing. For functions some really weird stuff happens:
>>
>> // this is C
>> #include <assert.h>
>> void foo() {}
> 
> How does this make any difference to whether you can call a function without parentheses or not?  You are arguing that for a function defined as foo(), foo; should mean call function foo, and I'm arguing that it should be a syntax error.  Neither of us want the C behavior of evaluating to the function address.
> 
> I think &foo should be the proper method of taking the address of a function, as it is in D.

I am glad this partially took care of itself.

Andrei

September 29, 2008
Steven Schveighoffer wrote:
> "Steven Schveighoffer" wrote
>> "Andrei Alexandrescu" wrote
>>>> Not really.  A function symbol by itself is the address of the function. A pointer symbol by itself is the address of the data it points to. It's the same.  I don't think you understood the detail that I stated, 'get address it's pointing to', not 'get address of the pointer'.
>>> I understood very well. Your point is off by a mile, and getting only farther. Please understand how you are making an elementary mistake.
>>>
>>> Consider:
>>>
>>> int x;
>>>
>>> Then if I only use "x", I am getting x's value (an lvalue in fact), not its address. Now consider:
>>>
>>> int * x;
>>>
>>> Then if I only use "x", I am getting x's value, which is the address of an int.
>>>
>>> In neither case is it possible for x and &x to mean the same thing. For functions some really weird stuff happens:
>>>
>>> // this is C
>>> #include <assert.h>
>>> void foo() {}
>> How does this make any difference to whether you can call a function without parentheses or not?  You are arguing that for a function defined as foo(), foo; should mean call function foo, and I'm arguing that it should be a syntax error.  Neither of us want the C behavior of evaluating to the function address.
>>
>> I think &foo should be the proper method of taking the address of a function, as it is in D.
> 
> This is what happens when you can't explain yourself correctly.  Stop typing your vehement response about how I am an idiot right now :)  I realize my mistake in the statements above.
> 
> I think the problem you cited with how foo is equivalent to &foo in C is bad.  I think we are getting sidetracked here, though.  The point I really want to state is that foo; shouldn't mean calling a function named foo.

"State" is very accurate, because aside from stating the point you bring nothing to support it.

> I don't think it should mean the address of the function, although it seems consistent with C pointers (IMO, it seems like &foo shouldn't even compile in C if foo means 'address of foo' already).  &foo sounds correct to me, "address of foo."

No. It does NOT seem and is NOT even remotely consistent with C pointers because x is not the same thing as &x for all symbols in C except functions. Please work through this with books and test programs and all, until you fully understand it. It is important.

> Bottom line, I'm not defending the way C takes addresses of functions, but I think the requirement C has to use parentheses to call functions helps to clarify the intentions of the function author, and makes the code clearer.

I agree, and I'd agree even more if you replaced "think" with "believe". I hope you also agree you have brought nothing of significance to support your thought/belief, while you have received plenty against.

I also agree that Sergey, Bill, and others did bring up good points in support for the required trailing "()". It would be more fertile to continue discussing those.


Andrei