October 01, 2008
Tue, 30 Sep 2008 23:58:14 +0800,
KennyTM~ wrote:
> P.S. *: "in" was "invariant scope". When did it changed to "const scope"??

I don't know whether it ever was invariant, but the current implementation is correct IMO: "in" contract means that you guarantee not to change the received object.  Const enforces exactly this guarantee.  Invariant is more restrictive in that it also requires a guarantee from the caller that the object will never change in the future, therefore disallowing mutable objects for "in" parameters.  This contract doesn't quite associate with an "in" keyword to me.
October 01, 2008
Benji Smith wrote:
> Andrei Alexandrescu wrote:
>> 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.
> 
> I'd like to propose another principle of language design:
> 
> 3) Consistency -- The expression of a semantic construct should always use the same syntax. Likewise, multiple uses of the same syntactic constructs should always result in the same semantics.

Consistency is good, but that's not consistency.

http://www.merriam-webster.com/dictionary/consistency

agreement or harmony of parts or features to one another or a whole :
correspondence  ; specifically : ability to be asserted together without
contradiction

An example of consistency is that user-defined operators have the same
syntax and precedence as built-in operators.

> Based on that principle, I'd argue that function-calling should either always use parentheses, or it should never use parentheses.

Yah I'd like that too. It's economy of syntax.

> Requiring parentheses for some function calls, but not for others violates the principle of consistency.

No. It violates economy of syntax. There are many syntaxes for the same
semantics. (I'll also note that Perl does not abide to economy of syntax
- see Tim Toady and all that.)

> In my prioritization of language-design principles, consistency is more important then syntactic economy.

Mine too. You just got a few terms jumbled.

> Based on those principles, I believe that the parentheses should be mandatory for all function calls.

That needs revision.


Andrei
October 01, 2008
Benji Smith wrote:
> Andrei Alexandrescu wrote:
>> 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.
> 
> I'd like to propose another principle of language design:
> 
> 3) Consistency -- The expression of a semantic construct should always use the same syntax. Likewise, multiple uses of the same syntactic constructs should always result in the same semantics.
> 
> Based on that principle, I'd argue that function-calling should either always use parentheses, or it should never use parentheses.
> 
> Requiring parentheses for some function calls, but not for others violates the principle of consistency.
> 
> In my prioritization of language-design principles, consistency is more important then syntactic economy.
> 
> Based on those principles, I believe that the parentheses should be mandatory for all function calls.
> 
> --benji

I was about to post a very similar post (it's still in my drafts folder)
besides fully agreeing with the above, I'll add the following:
operator & in D is not consistent.

int x;
auto y = &x; // y is int* (i.e pointer to int)

int func(int);
auto f = &func; // consistent with the above:
// f's type is - int function(int); i.e function pointer.

let's try a class:
class Test {
  int x;
  int func(int);
}

auto test = new Test();
auto y = &test.x; // consistent with the above
auto g = &test.func; // this is inconsistent!
in the above g is a delegate which is not a function pointer.
just as int* is different from int[]. you wouldn't expect to get an
int[] in the above, would you?

a more consistent approach would be to have:
- func and obj.method to be treated as delegates, of course for function
pointers there should be an implicit cast to delegate.
- &func and &obj.method would be strictly function pointers.
- using parentheses is mandatory for function calls.

IMHO, current low usage of delegates is not a reason to keep the current syntax but rather a result of the current syntax.

--Yigal
October 01, 2008
Simen Kjaeraas wrote:
> On Wed, 01 Oct 2008 07:58:20 +0200, Benji Smith <dlanguage@benjismith.net> 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
>>
>> One thing that I've found especially annoying about the current implementation is this:
>>
>>    x.y = 3; // Working code
>>    x.y += 3; // Broken, if x.y is actually a function
>>    x.y = x.y + 3; // Ugly work-around
>>
>> I've been bitten by this at least a dozen different times. Having a real property syntax would eliminate cases like that.
>>
>> --benji
> 
> It seems we will soon get reference return values, in which case this would
> no longer be a problem. I have also written a property template that enables
> things such as that, but it would also benefit immensely from reference
> return values.

Not quite. Sorry, I woke up all negative this morning :o).

Consider the .length property for built-in arrays. Better yet, consider you implement your own array and want to define a .length property.

You don't want it to return a reference! You want to have control over the assignment so that you execute the actual array change.

What I'd proposed to Walter for a long time is to allow a.b @= c to work if a.b = a.b @ c works. I'm sure people around here will find reasons to dislike that :o).


Andrei
October 01, 2008
Yigal Chripun wrote:
> Benji Smith wrote:
>> Andrei Alexandrescu wrote:
>>> 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.
>> I'd like to propose another principle of language design:
>>
>> 3) Consistency -- The expression of a semantic construct should always
>> use the same syntax. Likewise, multiple uses of the same syntactic
>> constructs should always result in the same semantics.
>>
>> Based on that principle, I'd argue that function-calling should either
>> always use parentheses, or it should never use parentheses.
>>
>> Requiring parentheses for some function calls, but not for others
>> violates the principle of consistency.
>>
>> In my prioritization of language-design principles, consistency is more
>> important then syntactic economy.
>>
>> Based on those principles, I believe that the parentheses should be
>> mandatory for all function calls.
>>
>> --benji
> 
> I was about to post a very similar post (it's still in my drafts folder)
> besides fully agreeing with the above, I'll add the following:
> operator & in D is not consistent.
> 
> int x;
> auto y = &x; // y is int* (i.e pointer to int)
> 
> int func(int);
> auto f = &func; // consistent with the above:
> // f's type is - int function(int); i.e function pointer.
> 
> let's try a class:
> class Test {
>   int x;
>   int func(int);
> }
> 
> auto test = new Test();
> auto y = &test.x; // consistent with the above
> auto g = &test.func; // this is inconsistent!
> in the above g is a delegate which is not a function pointer.
> just as int* is different from int[]. you wouldn't expect to get an
> int[] in the above, would you?
> 
> a more consistent approach would be to have:
> - func and obj.method to be treated as delegates, of course for function
> pointers there should be an implicit cast to delegate.
> - &func and &obj.method would be strictly function pointers.
> - using parentheses is mandatory for function calls.

A delegate /is/ a function pointer, more precisely, a pointer to function packed with a pointer to a value.

This also seems to reveal a lack of understanding of how class methods work. What function would you make &obj.method point to?


Andrei
October 01, 2008
KennyTM~ wrote:
> Simen Kjaeraas wrote:
>> On Wed, 01 Oct 2008 07:58:20 +0200, Benji Smith <dlanguage@benjismith.net> 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
>>>
>>> One thing that I've found especially annoying about the current implementation is this:
>>>
>>>    x.y = 3; // Working code
>>>    x.y += 3; // Broken, if x.y is actually a function
>>>    x.y = x.y + 3; // Ugly work-around
>>>
>>> I've been bitten by this at least a dozen different times. Having a real property syntax would eliminate cases like that.
>>>
>>> --benji
>>
>> It seems we will soon get reference return values, in which case this would
>> no longer be a problem. I have also written a property template that enables
>> things such as that, but it would also benefit immensely from reference
>> return values.
>>
> 
> It's still an issue if we want to support property setters, say
> 
>   class Time {
>     private double seconds;
> 
>     invariant /*pure?*/ double minutes () { return seconds/60.; }
>     void minutes (invariant double x) { seconds = x*60.; }
>   }
> 
> You cannot return a double& when calling .minutes because it simply does not exist. Therefore, the interpreter have to clever enough to convert
> 
>   t.minutes += 2;
> 
> into
> 
>   t.minutes = t.minutes + 2;
> 
> i.e.
> 
>   t.minutes(t.minutes() + 2);
> 
> if .minutes does not return a reference. A similar problem also exist with .opIndexAssign and .opSliceAssign.

Ah, didn't see your post before I posted a similar argument.

Andrei
October 01, 2008
"KennyTM~" wrote
> Simen Kjaeraas wrote:
>> On Wed, 01 Oct 2008 07:58:20 +0200, Benji Smith <dlanguage@benjismith.net> 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
>>>
>>> One thing that I've found especially annoying about the current implementation is this:
>>>
>>>    x.y = 3; // Working code
>>>    x.y += 3; // Broken, if x.y is actually a function
>>>    x.y = x.y + 3; // Ugly work-around
>>>
>>> I've been bitten by this at least a dozen different times. Having a real property syntax would eliminate cases like that.
>>>
>>> --benji
>>
>> It seems we will soon get reference return values, in which case this
>> would
>> no longer be a problem. I have also written a property template that
>> enables
>> things such as that, but it would also benefit immensely from reference
>> return values.
>>
>
> It's still an issue if we want to support property setters, say
>
>   class Time {
>     private double seconds;
>
>     invariant /*pure?*/ double minutes () { return seconds/60.; }
>     void minutes (invariant double x) { seconds = x*60.; }
>   }
>
> You cannot return a double& when calling .minutes because it simply does not exist. Therefore, the interpreter have to clever enough to convert
>
>   t.minutes += 2;
>
> into
>
>   t.minutes = t.minutes + 2;
>
> i.e.
>
>   t.minutes(t.minutes() + 2);
>
> if .minutes does not return a reference. A similar problem also exist with .opIndexAssign and .opSliceAssign.

Yes yes!

vote++

-Steve


October 01, 2008
Andrei Alexandrescu wrote:
> Yigal Chripun wrote:
>> Benji Smith wrote:
>>> Andrei Alexandrescu wrote:
>>>> 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.
>>> I'd like to propose another principle of language design:
>>>
>>> 3) Consistency -- The expression of a semantic construct should always use the same syntax. Likewise, multiple uses of the same syntactic constructs should always result in the same semantics.
>>>
>>> Based on that principle, I'd argue that function-calling should either always use parentheses, or it should never use parentheses.
>>>
>>> Requiring parentheses for some function calls, but not for others violates the principle of consistency.
>>>
>>> In my prioritization of language-design principles, consistency is more important then syntactic economy.
>>>
>>> Based on those principles, I believe that the parentheses should be mandatory for all function calls.
>>>
>>> --benji
>>
>> I was about to post a very similar post (it's still in my drafts folder)
>> besides fully agreeing with the above, I'll add the following:
>> operator & in D is not consistent.
>>
>> int x;
>> auto y = &x; // y is int* (i.e pointer to int)
>>
>> int func(int);
>> auto f = &func; // consistent with the above:
>> // f's type is - int function(int); i.e function pointer.
>>
>> let's try a class:
>> class Test {
>>   int x;
>>   int func(int);
>> }
>>
>> auto test = new Test();
>> auto y = &test.x; // consistent with the above
>> auto g = &test.func; // this is inconsistent!
>> in the above g is a delegate which is not a function pointer.
>> just as int* is different from int[]. you wouldn't expect to get an
>> int[] in the above, would you?
>>
>> a more consistent approach would be to have:
>> - func and obj.method to be treated as delegates, of course for function
>> pointers there should be an implicit cast to delegate.
>> - &func and &obj.method would be strictly function pointers.
>> - using parentheses is mandatory for function calls.
> 
> A delegate /is/ a function pointer, more precisely, a pointer to function packed with a pointer to a value.
> 
> This also seems to reveal a lack of understanding of how class methods work. What function would you make &obj.method point to?
> 
> 
> Andrei

I understand a delegate as a struct of two pointers as you said so yourself, above. an int[] != int* and so does a delegate != [C like] function pointer.

I'd make &obj.method to be the function pointer stored in the delegate.
so if a delegate contains two pointers (function pointer and context
pointer) I'd take the first with & and the other with a property of the
delegate as a possible syntax.
a delegate should have both a ptr and a context properties.
this can be used for example when calling C code.

just like you can have a D array and call a C function with
C_func(array.ptr, array.length);

C_function_which_calls_d_delegate(dg.ptr, dg.context);
OR
C_function_which_calls_d_delegate(&dg, dg.context);

in D code you'd probably use the delegate form more often than the function pointer, at least for regular application coding stuff.
October 01, 2008
Yigal Chripun wrote:
> Andrei Alexandrescu wrote:
>> Yigal Chripun wrote:
>>> Benji Smith wrote:
>>>> Andrei Alexandrescu wrote:
>>>>> 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.
>>>> I'd like to propose another principle of language design:
>>>>
>>>> 3) Consistency -- The expression of a semantic construct should always
>>>> use the same syntax. Likewise, multiple uses of the same syntactic
>>>> constructs should always result in the same semantics.
>>>>
>>>> Based on that principle, I'd argue that function-calling should either
>>>> always use parentheses, or it should never use parentheses.
>>>>
>>>> Requiring parentheses for some function calls, but not for others
>>>> violates the principle of consistency.
>>>>
>>>> In my prioritization of language-design principles, consistency is more
>>>> important then syntactic economy.
>>>>
>>>> Based on those principles, I believe that the parentheses should be
>>>> mandatory for all function calls.
>>>>
>>>> --benji
>>> I was about to post a very similar post (it's still in my drafts folder)
>>> besides fully agreeing with the above, I'll add the following:
>>> operator & in D is not consistent.
>>>
>>> int x;
>>> auto y = &x; // y is int* (i.e pointer to int)
>>>
>>> int func(int);
>>> auto f = &func; // consistent with the above:
>>> // f's type is - int function(int); i.e function pointer.
>>>
>>> let's try a class:
>>> class Test {
>>>   int x;
>>>   int func(int);
>>> }
>>>
>>> auto test = new Test();
>>> auto y = &test.x; // consistent with the above
>>> auto g = &test.func; // this is inconsistent!
>>> in the above g is a delegate which is not a function pointer.
>>> just as int* is different from int[]. you wouldn't expect to get an
>>> int[] in the above, would you?
>>>
>>> a more consistent approach would be to have:
>>> - func and obj.method to be treated as delegates, of course for function
>>> pointers there should be an implicit cast to delegate.
>>> - &func and &obj.method would be strictly function pointers.
>>> - using parentheses is mandatory for function calls.
>> A delegate /is/ a function pointer, more precisely, a pointer to
>> function packed with a pointer to a value.
>>
>> This also seems to reveal a lack of understanding of how class methods
>> work. What function would you make &obj.method point to?
>>
>>
>> Andrei
> 
> I understand a delegate as a struct of two pointers as you said so
> yourself, above. an int[] != int* and so does a delegate != [C like]
> function pointer.
> 
> I'd make &obj.method to be the function pointer stored in the delegate.

What is the signature of that function?

Andrei

October 01, 2008
Andrei Alexandrescu wrote:
> Yigal Chripun wrote:
>> Andrei Alexandrescu wrote:
>>> Yigal Chripun wrote:
>>>> Benji Smith wrote:
>>>>> Andrei Alexandrescu wrote:
>>>>>> 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.
>>>>> I'd like to propose another principle of language design:
>>>>>
>>>>> 3) Consistency -- The expression of a semantic construct should always use the same syntax. Likewise, multiple uses of the same syntactic constructs should always result in the same semantics.
>>>>>
>>>>> Based on that principle, I'd argue that function-calling should either always use parentheses, or it should never use parentheses.
>>>>>
>>>>> Requiring parentheses for some function calls, but not for others violates the principle of consistency.
>>>>>
>>>>> In my prioritization of language-design principles, consistency is
>>>>> more
>>>>> important then syntactic economy.
>>>>>
>>>>> Based on those principles, I believe that the parentheses should be mandatory for all function calls.
>>>>>
>>>>> --benji
>>>> I was about to post a very similar post (it's still in my drafts
>>>> folder)
>>>> besides fully agreeing with the above, I'll add the following:
>>>> operator & in D is not consistent.
>>>>
>>>> int x;
>>>> auto y = &x; // y is int* (i.e pointer to int)
>>>>
>>>> int func(int);
>>>> auto f = &func; // consistent with the above:
>>>> // f's type is - int function(int); i.e function pointer.
>>>>
>>>> let's try a class:
>>>> class Test {
>>>>   int x;
>>>>   int func(int);
>>>> }
>>>>
>>>> auto test = new Test();
>>>> auto y = &test.x; // consistent with the above
>>>> auto g = &test.func; // this is inconsistent!
>>>> in the above g is a delegate which is not a function pointer.
>>>> just as int* is different from int[]. you wouldn't expect to get an
>>>> int[] in the above, would you?
>>>>
>>>> a more consistent approach would be to have:
>>>> - func and obj.method to be treated as delegates, of course for
>>>> function
>>>> pointers there should be an implicit cast to delegate.
>>>> - &func and &obj.method would be strictly function pointers.
>>>> - using parentheses is mandatory for function calls.
>>> A delegate /is/ a function pointer, more precisely, a pointer to function packed with a pointer to a value.
>>>
>>> This also seems to reveal a lack of understanding of how class methods work. What function would you make &obj.method point to?
>>>
>>>
>>> Andrei
>>
>> I understand a delegate as a struct of two pointers as you said so yourself, above. an int[] != int* and so does a delegate != [C like] function pointer.
>>
>> I'd make &obj.method to be the function pointer stored in the delegate.
> 
> What is the signature of that function?
> 
> Andrei
> 

say we have:
class Test {
  int method(int);
}

auto obj = new Test();
auto fPtr = &obj.method;

type of fPtr would be: int function(int); or in C syntax: int (*)(int);
are you asking because of C++ pointer-to-member-function types?
in C++: int (Test::*)(int); ?

You know C++ much better than most of us here (certainly better than me), in your experience, is that distinction useful?