August 12, 2003
That's a damn site better job than I was revving up for, Bill, so I'll merely say "hear, hear".

"Sean L. Palmer" <palmer.sean@verizon.net> wrote in message news:bha4n0$8q2$1@digitaldaemon.com...
> Walter has done so by sacrificing the language's ability to pass around constants except by copying them.  Think about big arrays of constants, or constant structures.
>
> To safely pass a constant by reference you have to be able to ensure that nobody will alter the original version.
>
> Once you start passing pointers around to various functions it becomes impossible to statically ascertain whether a given call will violate the constness of the data you are essentially passing in by reference.  Thus
to
> be certain, the compiler is forced to make a copy of all const data before passing it by reference.
>
> One way around this is make the static checking more robust, by say decorating the function signature with information about how the function modifies its reference parameters, and information about all functions
this
> function might call with those parameters so that checking can pursue all possible routes by which the function might alter the parameter.  Only
once
> this has been done can the compiler safely pass in the original const data instead of a copy.
>
> I believe the same problem exists for determining register saving when
using
> so-called fastcall calling conventions.  If you can determine a called function will not clobber a register, you are safe to assume you can leave values there over the call, and much saving and restoring can be prevented or at least delayed to the point where it must be done due to the limited number of registers.
>
> With const, however, a protocol for parameter passing is not so easy.  You surely want to avoid copying data as much as possible, but occasionally it might be worth copying the data if that would be easier than burdening an entire call with restrictions.
>
> I certainly wouldn't want a language to permit anyone to modify data I declare as a constant.  Yet I want to be able to pass those constants to functions by reference without them being copied, so long as the function
is
> safe for passing const data to.  And if I try to pass a constant to a function that will potentially modify the contents, I wish to be warned at compile time instead of having silent copies generated that I can't keep track of.
>
> The compiler is probably much better at keeping tabs on what functions do
or
> do not alter their parameters than I am.  Therefore it should be assigned the task of adorning parameters with constness, as well as making sure
const
> data only gets passed by reference to those sorts of parameters.  An error would mention the const data passed, as well as point out at least one bit of offending code which prevents such a call, directly or indirectly, preferrably with some sort of route taken thru the code by which said problem could happen.  That would be enough info for a programmer that wished the function to actually be const-safe to eradicate the offending writes.
>
> Presto, D language syntax and grammar doesn't change, just the semantics slightly altered with a validity check inserted into the compiler, which
it
> should enforce to the best of its ability.
>
> Problem solved, everybody happy.  ;)  Except poor Walter, who would have
to
> implement it.
>
> Does anyone else think const in C++ is a poor attempt at letting the user decorate info that a sophisticated enough compiler could be able to figure out on its own?  Somewhat akin to the "register" keyword, which "aids" the compiler by disallowing any possibility of aliasing the value stored?
It's
> also something the compiler can figure out for you, something that modern compilers do.  They even do a pretty good job at it, from what I
understand,
> though C++'s laxity with pointers allows hideous data flow spaghetti that even the best compilers cannot sort out.
>
> Whatever it takes to get the compiler to make good code.  I often must
sound
> like I'm asking for alot.
>
> Another nice thing about keeping track of constness is that a pointer to constant data need never be freed, but that affects D very little since
it's
> built around garbage collection which gives you this anyway, for free.  ;)
>
> Yet another nice thing about passing constants is that it serves as an indicator to the optimizer that it might be able to generate a custom version of the function tailored with the constant completely inlined.
It's
> something people would want to do (identity matrix, anybody?) and I would expect the compiler to try to take advantage of such a situation.
>
> Sean
>
> "Bill Cox" <bill@viasic.com> wrote in message news:bh85p6$1324$1@digitaldaemon.com...
> > >>>3) Insufficient utility.
> > >>
> > >>You couldn't be more wrong
> > >
> > >
> > > Show me where it's useful. I finally stripped it out of my code, as it
> never
> > > found a bug after 15 years using it thinking it might help find a bug.
> >
> > Hi, Mathew.
> >
> > I would be very interested in hearing about the utility of const.  I'm not disputing your assertion, but I haven't had the same experience.
> >
> > We also dropped the use of const from our coding style at work, and I can't remember spending 1 minute tracking down a bug that const would have prevented.
> >
> > Perhaps there was a better way, but I feel like we were force to drop the use of 'const' pointers.  The problem is that it was too much for our guys to type on 90% of all object handles passed to functions.  I had a hell of a time enforcing it.  Overall, it seemed to hurt our programmers ability to work together.  Perhaps a 'variable' keyword or some such to declare what parameters get modified would have worked out.
> >
> > To me, it seems Walter has chosen good middle ground by supporting the use of 'const' only as a storage class modifier.
> >
> > Bill
>
>


August 12, 2003
Matthew Wilson wrote:
> That's a damn site better job than I was revving up for, Bill, so I'll
> merely say "hear, hear".

Hi, Matthew and Sean.

I very much respect both of your opinions on this.  I just have a somewhat different view point.

> "Sean L. Palmer" <palmer.sean@verizon.net> wrote in message
> 
>>Walter has done so by sacrificing the language's ability to pass around
>>constants except by copying them.  Think about big arrays of constants, or
>>constant structures.
>>
>>To safely pass a constant by reference you have to be able to ensure that
>>nobody will alter the original version.
>>
>>Once you start passing pointers around to various functions it becomes
>>impossible to statically ascertain whether a given call will violate the
>>constness of the data you are essentially passing in by reference.  Thus
> 
> to
> 
>>be certain, the compiler is forced to make a copy of all const data before
>>passing it by reference.

The compiler doesn't make any copies of constant arrays, as demonstraited with the following code and results:

const int [] a = [1, 2, 3, 4];

void writeOverConstArray(
    int [] a)
{
    int i;

    for(i = 0; i < 4; i++) {
	a[i] *= a[i];
    }
}

int main(char[][] args)
{
    int i;

    writeOverConstArray(a);
    for(i = 0; i < 4; i++) {
	printf("a[%d] = %d\n", i, a[i]);
    }
    return 0;
}

> const
a[0] = 1
a[1] = 4
a[2] = 9
a[3] = 16

The compiler simply doesn't prove that constant data isn't over-written.

...

>>I certainly wouldn't want a language to permit anyone to modify data I
>>declare as a constant.

I think this is the heart of the issue.  If you didn't feel that way, would you still want D to prove that constant data isn't modified?  I'm not questioning the validity of how you feel about it, but I doubt it's based on repeated experience of getting burned by having your constants overwritten.  I'd guess you've been using 'const' properly ever since it was introduced in C++, and haven't been in a position to find out how many bugs you've avoided.

Again, if Walter wants D to feel like a smooth highway to C++ programmers, including full constant protection might help.  Frankly, I've always been annoyed by it, since it makes it harder for our code to interface with other peoples code (our code doesn't use const protection, their code requires it).  We all wind up writing lots of casts to use eachother's code.

>>Does anyone else think const in C++ is a poor attempt at letting the user
>>decorate info that a sophisticated enough compiler could be able to figure
>>out on its own?  Somewhat akin to the "register" keyword, which "aids" the
>>compiler by disallowing any possibility of aliasing the value stored?

Yes.  Definately.

Why not just have the compiler try to prove that constant data is never modified, rather than having me put 'const' keywords in all my parameter declarations?  Is this what you're getting at?  If so, I'm for it.  It would eliminate all the cast nonsense 'const' creates when we use eachother's code.

> It's
> 
>>also something the compiler can figure out for you, something that modern
>>compilers do.  They even do a pretty good job at it, from what I
> 
> understand,
> 
>>though C++'s laxity with pointers allows hideous data flow spaghetti that
>>even the best compilers cannot sort out.
>>
>>Whatever it takes to get the compiler to make good code.  I often must
> 
> sound
> 
>>like I'm asking for alot.

So do the rest of us.

>>Another nice thing about keeping track of constness is that a pointer to
>>constant data need never be freed, but that affects D very little since
> 
> it's
> 
>>built around garbage collection which gives you this anyway, for free.  ;)
>>
>>Yet another nice thing about passing constants is that it serves as an
>>indicator to the optimizer that it might be able to generate a custom
>>version of the function tailored with the constant completely inlined.
> 
> It's
> 
>>something people would want to do (identity matrix, anybody?) and I would
>>expect the compiler to try to take advantage of such a situation.

I agree.  However, Walter's asserted that the compiler doesn't get to do such optimizations.  I'm always for making faster code.

Bill

August 12, 2003
The "const" qualifier is conceptually similar to Java's "throws" statements. Both are designed to make some static guarantees about the program's behavior.

However, taking care of the "throws" statements causes the programmers to fallback to the "catch and ignore all exceptions" mode.  Similarly, when it comes to usage of "const" (in C++) some programmers fall back to the "ignore const altogether and when I need to interface with software that actually uses const qualifiers, just cast them away".

This comes as no surprise: Manually taking care of things just complicates interfaces and makes the programmer bored.

So the main question is, should one make a programming language that will make programming fun, or one that allows for as strict static guarantees as possible?

D seems to have taken the first route, and I'm not complaining.

There would be two solutions for ensuring that no const object will change: one that examines the program text and automatically decorates the interfaces (or an internal database, or whatever) with the knowledge like "function x treats arguments y and z as constants", as per Sean's suggestion. (If I got it right). The problem is how you define the of library interfaces and how to make the whole thing visible to the programmer so that he knows what's going on.

Another could relying for run-time guarantees: placing the const data in a page with only read-only access, and turning hardware exceptions into D exceptions if possible. This is what C++ does (in addition to static guarantees of const) and that's my personal preference, too.

-Antti
August 12, 2003
"Sean L. Palmer" <palmer.sean@verizon.net> wrote in message news:bha4n0$8q2$1@digitaldaemon.com...
>
> Does anyone else think const in C++ is a poor attempt at letting the user decorate info that a sophisticated enough compiler could be able to figure out on its own?  Somewhat akin to the "register" keyword, which "aids" the compiler by disallowing any possibility of aliasing the value stored?
It's
> also something the compiler can figure out for you, something that modern compilers do.  They even do a pretty good job at it, from what I
understand,
> though C++'s laxity with pointers allows hideous data flow spaghetti that even the best compilers cannot sort out.

that's only "register" in C (afaik) register in C++ just means do things as
fast as pos,
try this as hello.cpp and hello.c with gcc
void loadup( int * fp, int iv ) { *fp = iv; }
int main( int argc, char * argv[] ) {
 register int foo;
 loadup( &foo, argc );
 return 0;
}

gcc hello.cpp (works no errors)
gcc hello.c ---
hello.c: In function `main':
hello.c:7: warning: address of register variable `foo' requested

I agree c++ const is very poor, and one of the biggest reasons ppl think gcc -03 is broken, if you use const slightly wrong it can optimise away code that should be run (and if you miss the odd volatile too).

I was just about to write a page on the great uses of const or final as
contracts between user and library writer
when I realised ... its all pointless (Walter you've make a convert out of
me, although volatile I think should still be possibly attached to an
pointer (hw reg address))

initially I considered two things, one was having "signal in" which like the
vhdl signal in means that the value is readable only by the function (unlike
now where I can use params as locals {I think this is bad and evil,
especially on risc arch's where is forces the compiler to flush the value
from reg to stack})
and having a way to say "this 'ere item I've passed you by reference can
will not get modified by the function I is calling"
so as an example I chose strcpy

if its extern then you have to say, this does not modify the src.
extern (C) c_strcpy( char * dest, final char * src, int len );

if it where in D then the compiler would know `*src` is only read.
void d_strcpy( char * dest, char * src, int len ) {
    while ( len--> 0 ) *dest++ = *src++;
}
either can be called with x_strcpy(  foo, bar, 3 ); or x_strcpy( foo, final
bar, 3 );
the latter would fail to compiler if for some reason x_strcpy was changed to
write into the value referenced by src.

of course this is all rather pointless as src and dest might overlap!

I do belive that there is a real need to have an "assert if modified by function" or a way to pass by reference a value that "should" not change (assert if it does) as part of the lang rather than adding asserts and checks all throughout your code (same for closures and reference to stack items, these should not be storeable on the heap or in a stack frame behind them (where you came from stack dir) [so passable but not storeable outside the local scope and not returnable (aliases to them would be restricted to the same rules too)]

you mention D as design by contract, will one of the contracts should be "I
don't modify your values you've passed me by reference"
this may seem like i'm saying give me const, but no, I would like a way a
library writer can say I'll not change your stuff, and an application writer
can say I only want to call this if it does no modify my values.
they are not const they are immutable within the local scope.


August 12, 2003
> 1) Too complicated (look at all the wierd rules and perterbations it
causes
> with template specialization and overloading).

I think this is right that the interaction is too complicated and it often
cause
duplicate code... but IMO we should modify the ways it works to avoid
the problems while keeping the benefits.

Also one think that make it complicate in C++ is the way declaration works
particulary when there are some indirection level (i.e. pointers). For
example,
in C++, we have

    const int a;
    int const a;

That mean the same thing. Alone, it is not too complicated but with pointers this can causes some confusion...

> 2) Too confusing.

I think we should modify the concept and have distinct keyword for each things... This is done at least in part by using in, inout and out parameter...

> 3) Insufficient utility.

I don't agree on that. I think if the compiler would be validating it and it would be impossible to break it (i.e. no const_cast or a different keyword for immutable data), then it would much more usefull.

> 4) Optimizers can't reliably use the info anyway.

It should be done in a way that the optimizer would be able to uses the information because the compiler should guaranties that constant data is not modified (by any means) and should not provide a way to break it.

We should not allows removing const anywhere... and we should not allows aliasing to occurs globally...

> 5) Ugly.
>

What it is ugly IMO with C++ solution is that it cause code duplication that should not occurs in some cases. I think this should be handled by having more keyword so that things can be expressed exactly...

For example, we should have a modifier "variable" that would be the opposite of "const" and we should also have "immuable" which would be the opposite of mutable (or does inout and out parameters is sufficient ?).  I don't think so at least when pointer are used.

I think that ideally we should be able to express the concept that
a function won't modify the data (in parameter) and the concept
that some data could not be modified (immutable data).

immutable data could be passed to const function without problem but it would be also be possible to define function that only accept immutable (or static) data so that the compiler could do some optimizations...

I think it should also be possible to express the constness of
something (for example the result of a function including members)
from the constness of something else (this, result of another function
call, parameters,...) including combinaisons... (i.e. any const implies
result is const).





> "Matthew Wilson" <matthew@stlsoft.org> wrote in message news:bgvdh2$1t4n$1@digitaldaemon.com...
> > What's the rationale again?
> >
> > "Walter" <walter@digitalmars.com> wrote in message news:bgvd22$1sna$1@digitaldaemon.com...
> > >
> > > "Chris Sokol" <chris@echosproject.org> wrote in message news:bgv1t6$1ijj$1@digitaldaemon.com...
> > > > Does D support it at all?
> > >
> > > D supports const as a storage class, but not as a type modifier.
> > >
> > >
> >
> >
>
>


August 12, 2003
Philippe, you're speaking my mind!

-i.

August 13, 2003
"Farmer" <itsFarmer.@freenet.de> a écrit dans le message de news:Xns93D2F2BCBD361itsFarmer@63.105.9.61...
> "Walter" <walter@digitalmars.com> wrote in news:bh1f3a$psi$1@digitaldaemon.com:
>
> > 4) Optimizers can't reliably use the info anyway.
>
> Optimizing *library writers* need that info to write optimized code that
is
> *robust*.
>
> Quotting from Phobos string.d:
>

I think that for "standard" libraries, the more information is available on
a
type, the more we can write code that could be optimized... This is
particulary
interesting for template where we could select the appropriate algorithm
depending on some attributes or modifier...

Ideally, it should be possible to extract modifier information and any
other usefull information when we want to... but when we do not want
we should be able to do 1 algorithm that works for all (supported) cases.

It may be interesting to be able to distinguate concept (an object that
appears const) and reality (an object in read-only memory) when
needed


August 13, 2003
"Bill Cox" <bill@viasic.com> wrote in message news:bhaupl$12t1$1@digitaldaemon.com...
> Matthew Wilson wrote:
[cut]
> >>Does anyone else think const in C++ is a poor attempt at letting the user decorate info that a sophisticated enough compiler could be able to figure out on its own?  Somewhat akin to the "register" keyword, which "aids" the compiler by disallowing any possibility of aliasing the value stored?
>
> Yes.  Definately.
>
> Why not just have the compiler try to prove that constant data is never modified, rather than having me put 'const' keywords in all my parameter declarations?  Is this what you're getting at?  If so, I'm for it.  It would eliminate all the cast nonsense 'const' creates when we use eachother's code.

From my point of view:
1) full const support is good
2) to write constst there is pain
So I think the const should be in a language, it should be explicit and editor,
 should be able to add consts to my code when I write it and ask for the
 anotation. In the worst case compiler could do it.
It is nice to see consts in souce code when you try to understand it, even when
 they can lie, it is an idicator what was intended. On the other side, they are
 not critical.


August 13, 2003
So you're saying you want a version of 'in' that works by reference always?

Usually the compiler would be smart enough to do that when appropriate, but one huge thing about pass by value vs. pass by reference is that either you're going to change the source data and you don't want the function to be affected (need pass by value) or you're going to change the source data (say in another thread) and want the function to get the updates immediately. 'inout' does this, but it allows the function to write to the parameters.

I believe the default parameter passing convention should be pass by value. I'll let you guys debate the usefulness of allowing the function to modify its value parameters.

If you want pass by reference, use 'in' for readonly reference, 'inout' for read/write reference, 'out' for writeonly reference.

Sean

"Mike Wynn" <mike.wynn@l8night.co.uk> wrote in message news:bhb8hd$1e0o$1@digitaldaemon.com...
> I do belive that there is a real need to have an "assert if modified by function" or a way to pass by reference a value that "should" not change (assert if it does) as part of the lang rather than adding asserts and checks all throughout your code (same for closures and reference to stack items, these should not be storeable on the heap or in a stack frame
behind
> them (where you came from stack dir) [so passable but not storeable
outside
> the local scope and not returnable (aliases to them would be restricted to
> the same rules too)]
>
> you mention D as design by contract, will one of the contracts should be
"I
> don't modify your values you've passed me by reference"
> this may seem like i'm saying give me const, but no, I would like a way a
> library writer can say I'll not change your stuff, and an application
writer
> can say I only want to call this if it does no modify my values. they are not const they are immutable within the local scope.


August 13, 2003
"Sean L. Palmer" <palmer.sean@verizon.net> wrote in message news:bhdq4e$qj2$1@digitaldaemon.com...
> So you're saying you want a version of 'in' that works by reference
always?
yes (basically)

currently for example
extern(Windows) BOOL ClipCursor( RECT * lpRect );
which in C is BOOL ClipCursor( CONST RECT * lpRect );
I guess is could be in D as
extern(Windows) BOOL ClipCursor( inout RECT lpRect );

but its not either realy its
extern(Windows) BOOL ClipCursor( in byref RECT lpRect );
as the API is defined to not to modify the RECT struct who's address you've
passed.

> Usually the compiler would be smart enough to do that when appropriate,
but
> one huge thing about pass by value vs. pass by reference is that either you're going to change the source data and you don't want the function to
be
> affected (need pass by value) or you're going to change the source data
(say
> in another thread) and want the function to get the updates immediately. 'inout' does this, but it allows the function to write to the parameters.

the compiler (like most C++/C compilers [and Java] I believe) assume that any value not marked as volatile are not modified by any other thread during the function, so globals can be cached at any time, but not cached over function calls [they might modify globals anyway]

> I believe the default parameter passing convention should be pass by
value.
> I'll let you guys debate the usefulness of allowing the function to modify its value parameters.
>
> If you want pass by reference, use 'in' for readonly reference, 'inout'
for
> read/write reference, 'out' for writeonly reference.

alas D does not have "reference" only pointer
(personally I think D should ditch pointer (has to be array slice) and allow
references `struct X * const foo` (auto derefed like java, which it already
has for object rather than c++ & which can't be rereferenced)
(obviously extern C need some rules about what to pass to remain compatible)