September 19, 2003
"Matthew Wilson" <matthew@stlsoft.org> wrote in message news:bkdt7v$1vih$1@digitaldaemon.com...
> Yesterday you raised the issue of the deblank() function having the wrong semantics. If we had a readonly keyword in D, the issue would be moot.

Not exactly. Consider the case of passing a parameter that is int****p. If it is 'readonly', what part of it is readonly? p? *p? **p? ***p? ****p? all of them? To resolve the issue with deblank(), more than just the string reference (i.e. p) would have to be readonly.

> I want code to be self-documenting, and the compiler to help enforce that (to a reasonable degree). If we had "readonly", that could be achieved. I don't give a fig for optimisations based on putative vs actual read-only, and all that other guff, and will be thoroughly unperturbed if that is
left
> out as it stands currently. But I remain strongly unconvinced that its absence from D is a +ve step. I'd be very interested to hear anyone to put forth an argument for such in response to what I (and others, who've commented similarly) want from a readonly/const keyword, rather than countering with the optimisation arguments.

Fair enough, and I had given some earlier in this thread <g>. Let's discuss the one about self-documentation. I agree with you that code should be self-documenting, as I've argued that comments are invariably missing, out-of-date, incomplete, or wrong.

The trouble with const being self-documenting is like checked exceptions in Java. Java issues a compile error if you call a function that throws something not listed in the exception specification. So, adding functionality to a function can entail going back through the entire static call chain editting all the exception specifications - so annoying that too many Java programmers, even good ones, tend to write try{f.foo();}catch{} just to shut up the compiler and get on with it. This, of course, completely subverts exception specifications and makes it far worse than not having exception specifications at all. (Even worse, despite being "exception specification correct", it is still possible to get exceptions not listed.)

Const has similar problems. You can't just ignore const if it is in the language, as you'll need to inevitably interface with code that uses it. The shortest, easiest way to do it is to just throw in a few const_cast's and move on. Even worse, as I pointed out, there are legal, defined ways to pull the rug out from under const without using undefined behavior of unions, casts, inline assembler, etc. While the situation isn't near as bad as with exception specifications, the self-documenting nature of it isn't at all reliable.

That said, there is a solution for const as a storage class. If it is put in read-only memory, it is const. No way around it, since the checking happens in hardware at runtime rather than compile time <g>.


September 19, 2003
In article <bkeah6$2k5u$1@digitaldaemon.com>, Walter wrote:
> The trouble with const being self-documenting is like checked exceptions in Java. Java issues a compile error if you call a function that throws something not listed in the exception specification. So, adding functionality to a function can entail going back through the entire static call chain editting all the exception specifications - so annoying that too many Java programmers, even good ones, tend to write try{f.foo();}catch{} just to shut up the compiler and get on with it. This, of course, completely subverts exception specifications and makes it far worse than not having exception specifications at all. (Even worse, despite being "exception specification correct", it is still possible to get exceptions not listed.)
>
> Const has similar problems. You can't just ignore const if it is in the language, as you'll need to inevitably interface with code that uses it. The shortest, easiest way to do it is to just throw in a few const_cast's and move on. Even worse, as I pointed out, there are legal, defined ways to pull the rug out from under const without using undefined behavior of unions, casts, inline assembler, etc. While the situation isn't near as bad as with exception specifications, the self-documenting nature of it isn't at all reliable.

This is a good summary of the similarities of const and exception specifications.

But then we need to concentrate on the differences between them.

- const is much more lightweight because it's just one bit of
  information in the interface. And you often get it right the first
  time. Even if you don't, you need to go through the call chain only
  once when you decide to add it.  Exception specifications, on the
  other hand, can grow and grow, and (if you want to do it right) you
  have to traverse the call chain every time when you add an exception.

- const affects the function's semantics directly. It tells what it can
  do with its arguments.  This is unlike exception specifications, which
  might not even have anything to do with the function that they pass
  through.

-Antti

September 19, 2003
"Philippe Mori" <philippe_mori@hotmail.com> wrote in message news:bid8ts$12qg$1@digitaldaemon.com...
> > D has deprecated: http://www.digitalmars.com/d/attribute.html
> But does it is possible to control in which module or on some other condition when deprecated take effects.

No. It applies to any use of a function.

> Also if the attribute can be depedant on other things (probably on versioning), then it might be possible to uses version for that purpose...

That might work.

> > class X { }
> >
> > template (Foo) {
> >     // your general template code goes here
> > }
> > template (Foo : X) {
> >     compileTimeError("You shouldn't instantiate Foo with types derived "
> >                      "from X");
> > }
> >
> > Upon finding an "instance Foo(X)" the compiler would blurt out something
> like
> >
> > line 567: Cannot instantiate Foo(X)
> > line 123: compileTimeError: You shouldn't instantiate Foo with types
> > derived from X
> >
>
> Compile time error is a must... This allows to check many constraints that are not directly supported by the language (like your example).
>
> This can be used to validate some constants to ensure no accidental
> changes would be done. This include some magic numbers, the size
> of a structure (it's alignment, member offset,...) and we should be able
> also to check some properties of classes and struct like:

This is now done with a new feature, static asserts.


September 19, 2003
"Antti Sykäri" <jsykari@gamma.hut.fi> wrote in message news:slrnbmlrr3.hfa.jsykari@pulu.hut.fi...
> This is a good summary of the similarities of const and exception specifications.
>
> But then we need to concentrate on the differences between them.
>
> - const is much more lightweight because it's just one bit of
>   information in the interface. And you often get it right the first
>   time. Even if you don't, you need to go through the call chain only
>   once when you decide to add it.  Exception specifications, on the
>   other hand, can grow and grow, and (if you want to do it right) you
>   have to traverse the call chain every time when you add an exception.

If you add a const to a type, that can ripple downwards through the call chain, affecting a lot of functions that are quite irrelevant. Inevitably, one of those rippled functions will be modifying its argument. This has happened to me :-(. There's a powerful temptation to just put in a const_cast and forget about it rather than reengineer.

> - const affects the function's semantics directly. It tells what it can
>   do with its arguments.  This is unlike exception specifications, which
>   might not even have anything to do with the function that they pass
>   through.

I agree that the const problem isn't nearly as bad as the exception specification one.


September 19, 2003
> > This is a good summary of the similarities of const and exception specifications.
> >
> > But then we need to concentrate on the differences between them.
> >
> > - const is much more lightweight because it's just one bit of
> >   information in the interface. And you often get it right the first
> >   time. Even if you don't, you need to go through the call chain only
> >   once when you decide to add it.  Exception specifications, on the
> >   other hand, can grow and grow, and (if you want to do it right) you
> >   have to traverse the call chain every time when you add an exception.
>
> If you add a const to a type, that can ripple downwards through the call chain, affecting a lot of functions that are quite irrelevant. Inevitably, one of those rippled functions will be modifying its argument. This has happened to me :-(. There's a powerful temptation to just put in a const_cast and forget about it rather than reengineer.
>
> > - const affects the function's semantics directly. It tells what it can
> >   do with its arguments.  This is unlike exception specifications, which
> >   might not even have anything to do with the function that they pass
> >   through.
>
> I agree that the const problem isn't nearly as bad as the exception specification one.
>

IMO the problem in C++ is the fact that we have to explictly
add const (for member functions) and not the other ways so it
is easy to forgot it and (and this will happen in a third-party library
you don't want to change)... so my opinion is that member function
(and in parameter) should be const by default...

That way most of the changes caused by an initial forgotten const would be avoided...

const does have its used to validate code... and to ensure that
an object would not be (reasonably) modified. In fact, if we
knows an object should not be modified, we uses const and
the compiler will issue an error if we accidently try to call a
function that modify the object.

Maybe, we should support constness only on predefined types,
enumerations, pointers, struct and class that are final (no virtual
members) and uses a constant interface for classes if we want
to prevent modifications:

interface Reader { }        // Only read
interface Writer : Reader { }        // Modify object

class MyClass : Reader, Writer { }  // Actual class

void f(Reader r) { }
void g(Writer w) { }

MyClass c;
f(reader);

Reader rc = c;
g(rc);                // Compile-time error

So my opinion is that we should have const but modify
it a bit to avoid the common pitfall of C++ (forgetting a
const on a method). For parameter, D is already better
that C++ since it has in, out and inout.... with the proper
default (i.e. in --- assuming in means const).


September 19, 2003
"Philippe Mori" <philippe_mori@hotmail.com> wrote in message news:bkg1k3$q8b$1@digitaldaemon.com...
> > > This is a good summary of the similarities of const and exception specifications.
> > >
> > > But then we need to concentrate on the differences between them.
> > >
> > > - const is much more lightweight because it's just one bit of
> > >   information in the interface. And you often get it right the first
> > >   time. Even if you don't, you need to go through the call chain only
> > >   once when you decide to add it.  Exception specifications, on the
> > >   other hand, can grow and grow, and (if you want to do it right) you
> > >   have to traverse the call chain every time when you add an
exception.
> >
> > If you add a const to a type, that can ripple downwards through the call chain, affecting a lot of functions that are quite irrelevant.
Inevitably,
> > one of those rippled functions will be modifying its argument. This has happened to me :-(. There's a powerful temptation to just put in a const_cast and forget about it rather than reengineer.
> >
> > > - const affects the function's semantics directly. It tells what it
can
> > >   do with its arguments.  This is unlike exception specifications,
which
> > >   might not even have anything to do with the function that they pass
> > >   through.
> >
> > I agree that the const problem isn't nearly as bad as the exception specification one.
> >
>
> IMO the problem in C++ is the fact that we have to explictly
> add const (for member functions) and not the other ways so it
> is easy to forgot it and (and this will happen in a third-party library
> you don't want to change)... so my opinion is that member function
> (and in parameter) should be const by default...
>
> That way most of the changes caused by an initial forgotten const would be avoided...
>
> const does have its used to validate code... and to ensure that
> an object would not be (reasonably) modified. In fact, if we
> knows an object should not be modified, we uses const and
> the compiler will issue an error if we accidently try to call a
> function that modify the object.
>
> Maybe, we should support constness only on predefined types,
> enumerations, pointers, struct and class that are final (no virtual
> members) and uses a constant interface for classes if we want
> to prevent modifications:
>
> interface Reader { }        // Only read
> interface Writer : Reader { }        // Modify object
>
> class MyClass : Reader, Writer { }  // Actual class
>
> void f(Reader r) { }
> void g(Writer w) { }
>
> MyClass c;
> f(reader);
>
> Reader rc = c;
> g(rc);                // Compile-time error
>
> So my opinion is that we should have const but modify
> it a bit to avoid the common pitfall of C++ (forgetting a
> const on a method). For parameter, D is already better
> that C++ since it has in, out and inout.... with the proper
> default (i.e. in --- assuming in means const).

in does not mean const. The in/out/inout applies to the parameter (reference) whereas the readonly applies to the object. They're quite different.

(I'm not calling it const, because "const" sucks as a term, and if D gets a "readonly" this will enable it to forgoe many of the problems with const without being accused of overlooking something)


September 20, 2003

> > So my opinion is that we should have const but modify
> > it a bit to avoid the common pitfall of C++ (forgetting a
> > const on a method). For parameter, D is already better
> > that C++ since it has in, out and inout.... with the proper
> > default (i.e. in --- assuming in means const).
>
> in does not mean const. The in/out/inout applies to the parameter (reference) whereas the readonly applies to the object. They're quite different.

I should have said implies... An in parameter should not be modified
inside a function (and if const support is eventually added to the
language, it should be the default for in parameters... and otherwise
it should be undefined what happen if we change a in parameter
(the change may or may not be visible to the caller depending
on werither a copy was made (a bit like in parameter in COM
programming... If a proxy is used (remote call), then the change
will not be visible and otherwise we should make changes...

>
> (I'm not calling it const, because "const" sucks as a term, and if D gets
a
> "readonly" this will enable it to forgoe many of the problems with const without being accused of overlooking something)
>

const and readonly are different concept... as generaly used. Typically by const, we want to talk about a C++ style constness (logical) while when readonly is used, we want to talk about hardware style readonly (physical).

Ideally both concept should be exprimable with proper construct...
I would like a language that would allows to express more such
concepts than C++ but it seems that we make tradeoffs...
we have added some new stuff (design by contract, static assertion,
...) but OTOH, we remove some usefull things, IMHO, that
where present in C++... I would prefer to have more even if
not everybody uses everything...



November 03, 2003
Walter wrote:

> The problem is that the standard doesn't preclude anyone *else* from
> changing the const data. For example:
> 
> void f(int *p1, const int *p2)
> {
>      int i = *p1;
>     (*p2)++;
      ^^^^^^^
Er, what?

The integer pointed to by p2 cannot be modified when accessed through p2. At least that's what the FAQ says. When looking at the ANSI C++ spec, i cannot figure anything out. It's apparently been written by people not at the peak of comprehesibility.

The DMC agrees with me. Where is a step which assigns to *p2 without casting away const-ness one or another way? What is a standard compliant way which would not result in undefined behaviour? And in which cases does const_cast exactly have well-defined behaviour?

>     int j = *p1;        // oops! j != i
> }
> 
>     int *a;
>     ...
>     f(a, a);
> 
> This is perfectly legal and defined behavior. 

?????????????????????????????????????????????????????
?? Am i going nuts or is actually something wrong ???
?????????????????????????????????????????????????????

-eye

November 04, 2003
"Ilya Minkov" <minkov@cs.tum.edu> wrote in message news:bo6k86$2dpj$1@digitaldaemon.com...
> Walter wrote:
>
> > The problem is that the standard doesn't preclude anyone *else* from changing the const data. For example:
> >
> > void f(int *p1, const int *p2)
> > {
> >      int i = *p1;
> >     (*p2)++;
>        ^^^^^^^
> Er, what?

Ah, I have it backwards. Put the const in front of p1.


1 2 3 4 5 6 7 8
Next ›   Last »