May 26, 2004
+1, AJ

Though it might seem draconian to some, defaulting arguments to read-only access would indeed avoid a ream of oft hard-to-find bugs. Would likely offer up some optimization opportunities also

- Kris.

"Arcane Jill" <Arcane_member@pathlink.com> wrote in message news:c920je$1jqr$1@digitaldaemon.com...
> In article <c91jku$11uv$1@digitaldaemon.com>, Andy Friesen says...
> >
> >C++ const means const methods, const references, and all the headaches that they entail.  The theory seems sound enough, but the compiler can't use const to optimize anything and I can't recall any instances offhand where const saved the day.
>
> Ooh, I can think of squillions of such examples. And at least one example
when
> one of my time "worked around" my const declaration with a pointer trick,
and
> held the project up for about two weeks while the whole team attempted to
figure
> out how and why the heap was getting corrupted! Our app was
multithreaded -
> that's when these things really matter.
>
> >I can, however, recall a whole lot of
> >compiler errors caused by forgetting to const this or that.
>
> That's what happens when you call functions written by other people who
DIDN'T
> use const.
>
> I've always thought that C++ would be a much better language if it
everything
> was const by default, and you needed a keyword, nonconst, say, to specify otherwise. That way, if you wrote a function like:
>
> >       char * strcpy(char * dst, char * src);
>
> it would fail to compile until you changed it to:
>
> >       char * strcpy(nonconst char * dst, char * src);
>
> (although the error would refer to the line that attempted to modify *dst,
not
> the declaration). As things stand, forgetting const is not a compile
error.
> Instead, it becomes impossible to use const unless you go the whole hog
and
> change every single function you call to use the C++ const convention.
>
> In the case of D, I would dearly love to be able to declare a function
like:
>
> >       void myFunction( in MyObject myObject )
>
> ****and have the compiler flag an error**** if the referenced object is modified. I cannot stress how greatly this would assist in bug catching.
>
> Right now the only way to do anything even remotely similar to this is:
>
> >       void myFunction( in MyObject myObject )
> >       in
> >       {
> >           myObject_backup = new MyObject(myObject);
> >       }
> >       out
> >       {
> >           assert(myObject == myObject_backup);
> >       }
> >       body
> >       {
> >           debug MyObject myObject_backup;
> >       }
>
> Sheesh!
>
> After all, putting const (or in, or nonconst, or whatever) into a function declaration is simply that - a contract which the function must fulfil. If
it
> fails to fulfil that contract, it's a bug.
>
> With all of D's emphasis on contracts, it baffles me why D doesn't
implement
> this most useful one.
>
> Arcane Jill
>
>


May 27, 2004
On Wed, 26 May 2004 08:02:24 -0700, Kris wrote:

> +1, AJ
> 
> Though it might seem draconian to some, defaulting arguments to read-only access would indeed avoid a ream of oft hard-to-find bugs. Would likely offer up some optimization opportunities also
> 
> - Kris.
> 

Oh is that what all this boils down to? In that case I support the idea as well.

Having worked with a language where it is impossible to change the value of function arguments, I at first thought this was a draconian 'feature'. But over the years now, I've come around to believing it has saved me from *so many* bugs AND it makes programming easier knowing that the arguments you pass to some function are never altered by that function. No side-effects! Wonderful! All parameters are only modified through explict assignments by the CALLING code and not the CALLED code.

If D is not going to do automatic copy-on-write (and I don't think it should), then having the default of read-only arguments AND being allowed to explictly nominate which arguments can be modified by a function, seems to be a good idea. One question that remains is at what point do we nominate the modifiable arguments - the caller or the called? In other words ...

If the caller does it (my preference so far)...
   A = FuncA( inout B, C, D)

If the called does it ...
   int FuncA( inout int X, int Y, int Z)
   { . . . }

I suppose it is not a compiler or a runtime error if the function attempts to modify read-only arguments because it could be said that its just using them as local variables. But maybe this needs more discussion and thought.

-- 
Derek
27/May/04 10:17:35 AM
May 27, 2004
On Thu, 27 May 2004 10:30:39 +1000, Derek Parnell <derek@psych.ward> wrote:
> On Wed, 26 May 2004 08:02:24 -0700, Kris wrote:
>
>> +1, AJ
>>
>> Though it might seem draconian to some, defaulting arguments to read-only
>> access would indeed avoid a ream of oft hard-to-find bugs. Would likely
>> offer up some optimization opportunities also
>>
>> - Kris.
>>
>
> Oh is that what all this boils down to? In that case I support the idea as
> well.
>
> Having worked with a language where it is impossible to change the value of
> function arguments, I at first thought this was a draconian 'feature'. But
> over the years now, I've come around to believing it has saved me from *so
> many* bugs AND it makes programming easier knowing that the arguments you
> pass to some function are never altered by that function. No side-effects!
> Wonderful! All parameters are only modified through explict assignments by
> the CALLING code and not the CALLED code.
>
> If D is not going to do automatic copy-on-write (and I don't think it
> should), then having the default of read-only arguments AND being allowed
> to explictly nominate which arguments can be modified by a function, seems
> to be a good idea. One question that remains is at what point do we
> nominate the modifiable arguments - the caller or the called? In other
> words ...
>
> If the caller does it (my preference so far)...
>    A = FuncA( inout B, C, D)
>
> If the called does it ...
>    int FuncA( inout int X, int Y, int Z)
>    { . . . }

It's going to have to be the latter I think, then it can be checked at compile time (in some/most/all? cases)
Also the function writer knows what access the function needs to it's parameters, not the caller.

> I suppose it is not a compiler or a runtime error if the function attempts
> to modify read-only arguments because it could be said that its just using
> them as local variables. But maybe this needs more discussion and thought.

I think it should be an error. If you want to modify them, then either:
 - they're incorrectly labelled read-only
 - you only want to modify them for the scope of the function, in which case what is wrong with:

 struct foo {
   int a;
 }

 int foobar(in foo a) {
   foo b = a;
   //modify/use b;
 }

Regan.

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
May 27, 2004
On Thu, 27 May 2004 12:59:10 +1200, Regan Heath wrote:

> On Thu, 27 May 2004 10:30:39 +1000, Derek Parnell <derek@psych.ward> wrote:
>> On Wed, 26 May 2004 08:02:24 -0700, Kris wrote:
>>
>>> +1, AJ
>>>
>>> Though it might seem draconian to some, defaulting arguments to
>>> read-only
>>> access would indeed avoid a ream of oft hard-to-find bugs. Would likely
>>> offer up some optimization opportunities also
>>>
>>> - Kris.
>>>
>>
>> Oh is that what all this boils down to? In that case I support the idea
>> as
>> well.
>>
>> Having worked with a language where it is impossible to change the value
>> of
>> function arguments, I at first thought this was a draconian 'feature'.
>> But
>> over the years now, I've come around to believing it has saved me from
>> *so
>> many* bugs AND it makes programming easier knowing that the arguments you
>> pass to some function are never altered by that function. No
>> side-effects!
>> Wonderful! All parameters are only modified through explict assignments
>> by
>> the CALLING code and not the CALLED code.
>>
>> If D is not going to do automatic copy-on-write (and I don't think it
>> should), then having the default of read-only arguments AND being allowed
>> to explictly nominate which arguments can be modified by a function,
>> seems
>> to be a good idea. One question that remains is at what point do we
>> nominate the modifiable arguments - the caller or the called? In other
>> words ...
>>
>> If the caller does it (my preference so far)...
>>    A = FuncA( inout B, C, D)
>>
>> If the called does it ...
>>    int FuncA( inout int X, int Y, int Z)
>>    { . . . }
> 
> It's going to have to be the latter I think, then it can be checked at
> compile time (in some/most/all? cases)
> Also the function writer knows what access the function needs to it's
> parameters, not the caller.
> 
>> I suppose it is not a compiler or a runtime error if the function
>> attempts
>> to modify read-only arguments because it could be said that its just
>> using
>> them as local variables. But maybe this needs more discussion and
>> thought.
> 
> I think it should be an error. If you want to modify them, then either:
>   - they're incorrectly labelled read-only
>   - you only want to modify them for the scope of the function, in which
> case what is wrong with:
> 
>   struct foo {
>     int a;
>   }
> 
>   int foobar(in foo a) {
>     foo b = a;
>     //modify/use b;
>   }
> 

Yeah, that makes sense. Also if the caller is worried about a function changing the parameters, the caller can pass a copy.

   int Xcopy = X;
   foobar( Xcopy );

-- 
Derek
27/May/04 11:58:28 AM
May 27, 2004
In article <c8vrut$1e87$1@digitaldaemon.com>, Andy Friesen says...
>
>Norbert Nemec wrote:
>
>> Andy Friesen wrote:
>> 
>> 
>>>imr1984 wrote:
>>>Are there any arguments for passing structs by value?
>> 
>> 
>> It is be faster for small structs. But I guess, if you want to go for speed, you would use inlining anyway, in which case it does not really matter. It just has to be clear what the semantics are, no matter what the compiler does to achive it.
>
>Why is it faster?  And how small is small?

Depends on reference and pointer semantics.  It is faster to copy small structs, because you can cache all or parts of them in registers.  Consider this common swap idiom:

struct foo {
int a;
int b;
}

// foo x : passed into function

if (x.a > x.b) {
int c = x.a;
x.a = x.b;
x.b = c;
}

If structs are pass-by-value, this needs to load x.a and x.b, write x.b to x.a, write x.a to x.b.  I assume enough optimization that c can be eliminated.  Thus there are four memory operations if the loop is true, two if not.

If pass by reference, and "aliasing" assumptions are C89 style, then there are at least 6 memory operations, because the structs may have changed between statements.

This is (one reason) why some C and C++ code will pass a struct by pointer, then copy pieces into local variables.  Local variables can be "registerized" but structs can only be registerized if the current thread can be assumed to be the only user of the struct.

Hopefully, D will use semantics that default to higher optimization and less aliasing,  (In contradiction of a previous suggestion of mine ;).

Kevin

>> Furthermore, it has to be clear how other languages are interfaced. If you want to interface a C function that takes a struct as value on the stack, you have to be able to specify that interface in D.
>
>extern(C/Windows/Pascal) mustn't do this; it defeats their entire reason to exist.  I'm suggesting behaviour for extern(D) only.
>
>  -- andy


May 27, 2004
Derek Parnell wrote:

> On Wed, 26 May 2004 08:02:24 -0700, Kris wrote:
> 
>> +1, AJ
>> 
>> Though it might seem draconian to some, defaulting arguments to read-only access would indeed avoid a ream of oft hard-to-find bugs. Would likely offer up some optimization opportunities also
>> 
>> - Kris.
>> 
> 
> Oh is that what all this boils down to? In that case I support the idea as well.
> 
> Having worked with a language where it is impossible to change the value of function arguments, I at first thought this was a draconian 'feature'. But over the years now, I've come around to believing it has saved me from *so many* bugs AND it makes programming easier knowing that the arguments you pass to some function are never altered by that function. No side-effects! Wonderful! All parameters are only modified through explict assignments by the CALLING code and not the CALLED code.

Abolishing side-effects completely would be a long step from the C philosophy and a rather radical change in D. I don't think, we can get all that far. Of course, other languages (especially functional languages) do it and it saves them a number of problems. But C/C++/D are not functional.

All I thought about was making 'in' parameters readonly within the function, instead of turning them into local variables that can be changed, but whose value is lost. Alternatively, you could have the compiler to automatically insert a copying instruction on read-only call-by-reference arguments.


> 
> If D is not going to do automatic copy-on-write (and I don't think it should), then having the default of read-only arguments AND being allowed to explictly nominate which arguments can be modified by a function, seems to be a good idea. One question that remains is at what point do we nominate the modifiable arguments - the caller or the called? In other words ...
> 
> If the caller does it (my preference so far)...
>    A = FuncA( inout B, C, D)
> 
> If the called does it ...
>    int FuncA( inout int X, int Y, int Z)
>    { . . . }

The second one if needed in any case (and is in the specs already) since 'inout' is a matter of the interface. Adding the first one would only be redundancy which is not exactly D style.

May 27, 2004
Kevin Bealer wrote:

> Hopefully, D will use semantics that default to higher optimization and less aliasing,  (In contradiction of a previous suggestion of mine ;).

I don't hope for too much in that respect. Aliasing is a fundamental problem in a language as soon as you have references. In Fortran77, it was trivial to avoid aliasing by simply stating that function arguments may not be aliased. This is, because function arguments were the only source of aliased symbols. Outside of a function, two different symbols always stand for two different objects in memory. Only in functions call, new names for symbols are introduced, so it is easy to prohibit this and have the problem solved completely.

In languages that have pointers, aliasing happens everywhere. Prohibiting aliased function arguments only captures the tip of the iceberg. A function might use pointers from all kinds of sources, nested data-structures or whatever.

May 27, 2004
In article <c8upj2$2m2j$1@digitaldaemon.com>, Norbert Nemec wrote:
> I believe that whole business of "in", "out" and "inout" arguments is flawed. My first expectation, when I saw these was, that that they are "copy-in/copy-out" arguments. The specs are not very precise when they talk

Hmm, hmm.

I just got a strange revelation...  since D doesn't have const, doesn't that actually mean that inout and in are practically the same thing? (If we're talking about classes that is. Yes, it means precisely that. "in" arguments can be clobbered ruthlessly.)

Actually I could think differently: since const can never be anything else than documentation of the programmer's intent, it isn't actually needed. "in" and "inout" could be as well replaced with C++'s const reference and inout with reference.

Except that an "in" parameter doesn't protect the programmer from accidents. It's precisely like a const T& parameter of C++, which is then const_cast<T&>:ed implicitly inside the function body.

I didn't even think (or test) about the value arguments (ints, structs
and the like) yet, maybe the in/inout stuff is just cleaner when you
take them into account.

-Antti

> about this question. Somehow, I have the feeling, that D tries to hide the complexity of reference/value arguments from the user, but, at the same time, obscures and cripples the concept completely.
> 
> My opinion: neither the C++ nor the D way are the solution. I don't know the solution, but it has to be out there somewhere.
> 
> 
> 
> Kris wrote:
> 
>> One cannot use 'inout' with a const struct, since by definition it's read-only.
>> 
>> - Kris
>> 
>> "Carlos Santander B." <carlos8294@msn.com> wrote in message news:c8udnv$205u$1@digitaldaemon.com...
>>> "imr1984" <imr1984_member@pathlink.com> escribió en el mensaje
>>> news:c8tbvq$fm$1@digitaldaemon.com
>>> | I think D needs a 'ref' keyword like C# has. This way large structs can
>> be
>>> | passed by reference without nasty pointers. The way i see it, this is
>> the
>>> only
>>> | way to support this because as Stewart says if you have a function
>>> exported from
>>> | a library, and it takes a struct, the only way for the compiler to know
>>> that the
>>> | exported func takes the struct by Ref is if its indicated in the
>> prototype
>>> with
>>> | the ref keyword.
>>> |
>>>
>>> What's wrong with inout?
>>>
>>> -----------------------
>>> Carlos Santander Bernal
>>>
>>>
> 


-- 
I will not be using Plan 9 in the creation of weapons of mass destruction to be used by nations other than the US.
May 28, 2004
Antti Sykäri wrote:

>In article <c8upj2$2m2j$1@digitaldaemon.com>, Norbert Nemec wrote:
>  
>
>>I believe that whole business of "in", "out" and "inout" arguments is
>>flawed. My first expectation, when I saw these was, that that they are
>>"copy-in/copy-out" arguments. The specs are not very precise when they talk
>>    
>>
>
>Hmm, hmm.
>
>I just got a strange revelation...  since D doesn't have const, doesn't
>that actually mean that inout and in are practically the same thing? (If
>we're talking about classes that is. Yes, it means precisely that. "in"
>arguments can be clobbered ruthlessly.)
>  
>
in and inout do behave slightly different for objects.

void test(A a)
{
   a = new A;
}

void test2(inout A a)
{
   a = new A;
}


void main()
{
   A a = new A;
   test(a);
   //what is a
   test2(a);
   //what is a
}


-- 
-Anderson: http://badmama.com.au/~anderson/
1 2 3 4
Next ›   Last »