Thread overview
free functions as attributes
Aug 04, 2004
Sean Kelly
Aug 04, 2004
Andy Friesen
Aug 04, 2004
Regan Heath
Aug 04, 2004
Andy Friesen
Aug 05, 2004
Regan Heath
August 04, 2004
Given this code:

# void attribute( char[] c ) {}
# void attribute( char c ) {}
#
# int main()
# {
#     char[] ary;
#     ary.attribute(); // (1) works
#     ary.attribute; // (2) no property 'attribute' for type 'char[]'
#
#     char c;
#     c.attribute(); // (3) no property 'attribute' for type 'char'
#     c.attribute; // (4) no property 'attribute' for type 'char'
#     return 0;
# }

I'd like to request some consistency.  If (1) works, then (3) should work as well.  And ideally, all four examples should work if this syntax is to be supported.  It seems odd that arrays are an exception in this case.


Sean


August 04, 2004
Sean Kelly wrote:
> Given this code:
> 
> # void attribute( char[] c ) {}
> # void attribute( char c ) {}
> # # int main()
> # {
> #     char[] ary;
> #     ary.attribute(); // (1) works
> #     ary.attribute; // (2) no property 'attribute' for type 'char[]'
> #     #     char c;
> #     c.attribute(); // (3) no property 'attribute' for type 'char'
> #     c.attribute; // (4) no property 'attribute' for type 'char'
> #     return 0;
> # }
> 
> I'd like to request some consistency.  If (1) works, then (3) should work as
> well.  And ideally, all four examples should work if this syntax is to be
> supported.  It seems odd that arrays are an exception in this case.

It looks handy, but I can't help but think that it's begging to introduce non-obvious behaviour into seemingly straightforward code.

I think it would be prudent to leave the rules as they are and see what happens.  When work on D 2.0 starts, it can be decided whether it should be removed or extended. (or neither)

I do think one small change should be made, however:

This behaviour should only occur when the first argument of the function is inout.

Things are just begging to get weird if a function mutates an array in some manner and is passed as an 'in' parameter under normal circumstances.  Hiding it behind method-like syntax would only make it worse: you don't expect 'real' methods to reallocate the 'this' reference part-way through. :)

 -- andy
August 04, 2004
On Wed, 04 Aug 2004 14:19:29 -0700, Andy Friesen <andy@ikagames.com> wrote:
> Sean Kelly wrote:
>> Given this code:
>>
>> # void attribute( char[] c ) {}
>> # void attribute( char c ) {}
>> # # int main()
>> # {
>> #     char[] ary;
>> #     ary.attribute(); // (1) works
>> #     ary.attribute; // (2) no property 'attribute' for type 'char[]'
>> #     #     char c;
>> #     c.attribute(); // (3) no property 'attribute' for type 'char'
>> #     c.attribute; // (4) no property 'attribute' for type 'char'
>> #     return 0;
>> # }
>>
>> I'd like to request some consistency.  If (1) works, then (3) should work as
>> well.  And ideally, all four examples should work if this syntax is to be
>> supported.  It seems odd that arrays are an exception in this case.
>
> It looks handy, but I can't help but think that it's begging to introduce non-obvious behaviour into seemingly straightforward code.
>
> I think it would be prudent to leave the rules as they are and see what happens.  When work on D 2.0 starts, it can be decided whether it should be removed or extended. (or neither)
>
> I do think one small change should be made, however:
>
> This behaviour should only occur when the first argument of the function is inout.
>
> Things are just begging to get weird if a function mutates an array in some manner and is passed as an 'in' parameter under normal circumstances.  Hiding it behind method-like syntax would only make it worse: you don't expect 'real' methods to reallocate the 'this' reference part-way through. :)

If an array is passed as 'in' (the default) you cannot change the array reference, you can change the data, append to the data, change the length, etc.. the 'this' reference is the array reference, and it cannot be changed, so I don't understand what you're saying.

Regan

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
August 04, 2004
Regan Heath wrote:

> On Wed, 04 Aug 2004 14:19:29 -0700, Andy Friesen <andy@ikagames.com> wrote:
> 
>> Sean Kelly wrote:
>>
>>> Given this code:
>>>
>>> # void attribute( char[] c ) {}
>>> # void attribute( char c ) {}
>>> # # int main()
>>> # {
>>> #     char[] ary;
>>> #     ary.attribute(); // (1) works
>>> #     ary.attribute; // (2) no property 'attribute' for type 'char[]'
>>> #     #     char c;
>>> #     c.attribute(); // (3) no property 'attribute' for type 'char'
>>> #     c.attribute; // (4) no property 'attribute' for type 'char'
>>> #     return 0;
>>> # }
>>>
>>> I'd like to request some consistency.  If (1) works, then (3) should work as
>>> well.  And ideally, all four examples should work if this syntax is to be
>>> supported.  It seems odd that arrays are an exception in this case.
>>
>>
>> It looks handy, but I can't help but think that it's begging to introduce non-obvious behaviour into seemingly straightforward code.
>>
>> I think it would be prudent to leave the rules as they are and see what happens.  When work on D 2.0 starts, it can be decided whether it should be removed or extended. (or neither)
>>
>> I do think one small change should be made, however:
>>
>> This behaviour should only occur when the first argument of the function is inout.
>>
>> Things are just begging to get weird if a function mutates an array in some manner and is passed as an 'in' parameter under normal circumstances.  Hiding it behind method-like syntax would only make it worse: you don't expect 'real' methods to reallocate the 'this' reference part-way through. :)
> 
> 
> If an array is passed as 'in' (the default) you cannot change the array reference, you can change the data, append to the data, change the length, etc.. the 'this' reference is the array reference, and it cannot be changed, so I don't understand what you're saying.

Actually I'm not sure if I agree with what I wrote when I posted that, but what I meant was that, if you wrote something like this:

    import std.stdio;

    void dupe(char[] This, char[] str, int count) {
        for (int i = 0; i < count; i++) {
            This ~= str;
        }
    }

    int main() {
        char[] ni;
        ni.dupe("NI!", 999); // set ni to "NI!NI!NI!....."

        writefln(ni);
        return 0;
    }

You'd be in for a surprise.  The string 'ni' is not going to change, because all those concatenations are more than enough to cause D to reallocate the array.  Since 'This' is not an inout parameter, the reallocation isn't reflected back to the argument passed.

But, I don't think this is such a great idea anymore.  This wrinkle in the language is, as far as I know, used primarily for string functions, which typically don't mutate strings in-place anyway.

 -- andy
August 05, 2004
On Wed, 04 Aug 2004 16:50:53 -0700, Andy Friesen <andy@ikagames.com> wrote:
> Regan Heath wrote:
>
>> On Wed, 04 Aug 2004 14:19:29 -0700, Andy Friesen <andy@ikagames.com> wrote:
>>
>>> Sean Kelly wrote:
>>>
>>>> Given this code:
>>>>
>>>> # void attribute( char[] c ) {}
>>>> # void attribute( char c ) {}
>>>> # # int main()
>>>> # {
>>>> #     char[] ary;
>>>> #     ary.attribute(); // (1) works
>>>> #     ary.attribute; // (2) no property 'attribute' for type 'char[]'
>>>> #     #     char c;
>>>> #     c.attribute(); // (3) no property 'attribute' for type 'char'
>>>> #     c.attribute; // (4) no property 'attribute' for type 'char'
>>>> #     return 0;
>>>> # }
>>>>
>>>> I'd like to request some consistency.  If (1) works, then (3) should work as
>>>> well.  And ideally, all four examples should work if this syntax is to be
>>>> supported.  It seems odd that arrays are an exception in this case.
>>>
>>>
>>> It looks handy, but I can't help but think that it's begging to introduce non-obvious behaviour into seemingly straightforward code.
>>>
>>> I think it would be prudent to leave the rules as they are and see what happens.  When work on D 2.0 starts, it can be decided whether it should be removed or extended. (or neither)
>>>
>>> I do think one small change should be made, however:
>>>
>>> This behaviour should only occur when the first argument of the function is inout.
>>>
>>> Things are just begging to get weird if a function mutates an array in some manner and is passed as an 'in' parameter under normal circumstances.  Hiding it behind method-like syntax would only make it worse: you don't expect 'real' methods to reallocate the 'this' reference part-way through. :)
>>
>>
>> If an array is passed as 'in' (the default) you cannot change the array reference, you can change the data, append to the data, change the length, etc.. the 'this' reference is the array reference, and it cannot be changed, so I don't understand what you're saying.
>
> Actually I'm not sure if I agree with what I wrote when I posted that, but what I meant was that, if you wrote something like this:
>
>      import std.stdio;
>
>      void dupe(char[] This, char[] str, int count) {
>          for (int i = 0; i < count; i++) {
>              This ~= str;
>          }
>      }
>
>      int main() {
>          char[] ni;
>          ni.dupe("NI!", 999); // set ni to "NI!NI!NI!....."
>
>          writefln(ni);
>          return 0;
>      }
>
> You'd be in for a surprise.  The string 'ni' is not going to change, because all those concatenations are more than enough to cause D to reallocate the array.  Since 'This' is not an inout parameter, the reallocation isn't reflected back to the argument passed.

I don't think it matters whether it reallocates or not, I think it's simply a matter of the original string having a length of 0 and the modified data (if not reallocated) being longer than that.

You can however modify a character within the original string length and that change is reflected back to the argument passed.

See my test case below.

> But, I don't think this is such a great idea anymore.  This wrinkle in the language is, as far as I know, used primarily for string functions, which typically don't mutate strings in-place anyway.

The current concept makes me slightly uncomfortable for no reason I can put into words.

I still think 'in' should enforce 'const', and there should be a way to specify const data that an array references, which cannot be changed by any reference to that data.


import std.stdio;

void addOne(char[] s)
{
	s.length = s.length+1;
	s[s.length-1] = 'A';
}

void changeOne(char[] s)
{
	s[0] = s[0]+1;
}

int main() {
	char[] ni = "NO!";

	ni.length = 100; ni.length = 3;
	
	addOne(ni);
	writefln(ni);
	
	changeOne(ni);
	writefln(ni);
	
	return 0;
}




Regan.

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/