Re: Variables in for loop (style issue)
Walter Bright wrote:
Andrei Alexandrescu (See Website For Email) wrote:
My direct experience contradicts that. The notion of a read-only
view of
an otherwise modifiable object is immensely useful in a number of
cases,
particularly when it comes to passing it to a function. Very often
functions must not modify data that their callers can righteously
modify, and const allows expressiong that.
But type modifier const does not express that. The C++ Standard
specifically allows const_cast to operate on reference to const, and
modify it. Aliases to the reference can also modify it. Only storage
class const guarantees the data is constant (but then the callers
cannot
righteously modify it, either).
I totally understand that. However I repeat my point which seems to not
have been understood: const the type modifier has value _for me_.
I don't use const_cast. I just grepped the ~$40KLOC project I mess with
for const_cast, and found 27 occurrences. Of these, 23 actually _add_
const when passing parameters to functions so as to prevent the
functions, which possibly might change signature in the future, from
changing their argument. Example:
qn_dtanh_vf_vf(n_2, const_cast<const float*>(y_2), phi_prime_3);
The 4 left save typing by implementing the const/nonconst accessor
idiom.
One thing that I find annoying in Java and D is that I never know
whether a function is supposed to (1) mess with some data so I
must pass
it a preemptive copy of my data, or (2) promises to not modify the
data.
The latter case leaves Damocles' sword upon the head of that
function's
callers because the language is unable to express read-only views.
C++ does not support readonly views of data (I've quoted the C++
Standard paragraph that says it does not). If you need a language
guarantee, the C++ 'constT&' is no more expressive than '/*const*/T&'.
I think this discussion could go on forever because we talk about
different things. We both discuss "vegetable milk" but you have in mind
"rice milk" and I have in mind "soy milk". Whenever I mention some
virtue of "vegetable milk", you reply that "vegetable milk" doesn't
really have it. But we really have different representations of the
notion in our minds.
To clarify: when I mention the virtues of a read-only view of otherwise
writable data, I do NOT discuss C++'s const sensum strictum. I do
understand that C++'s const does not enforce that ideal because it
allows const_cast to remove that illusion even in a well-defined
program. I understand. Please. I understand. Now take that lamp out of
my eyes :o).
My point is that readonly views _are_ useful, and that C++'s imperfect
approximation _is_ useful to at least one person. D dropped the
approximation entirely, possibly in part because of its imperfection,
and IMHO that is a mistake. At best it would implement the abstraction
perfectly; the next good thing would be to implement a better
approximation; and the worst is to keep on dwelling surreptitiously on
how the imperfection in C++'s implementation makes it worthless to
implement in D and everybody's better off without.
So absent such a concept, D is forced to copy data around _more_,
o to
expose itself to _more bugs_.
I don't agree, as the programmer's API documentation promising to not
modify the arguments is as good as C++ 'const T&' is. I agree that
some
sort of language guarantee of this would be better, but const T&
isn't it.
It is in my own programs. I don't const_cast around, grep is my proof,
the compiler takes care of the rest, and that makes me derive a net
benefit from C++'s const.
I think it's productive to take the discussion away from restating C++'s
const imperfections. And instead of yet another posting of the
paragraphs in the C++ standard showing when const_cast is legit, I'd
take nails on chalkboard any day of the week.
I also feel that if you feel you are forced to copy data to pass to
functions because you don't know what the function will do to it, that
the function's documentation is inadequate and you probably
shouldn't be
using it.
It could be my own function which is work in progress and modifies data
inadvertently as a bug although it doesn't want to. But anyhow, don't we
all know the power of type systems as enforceable documentation?
At any rate, I think it's a mistake to draw conclusions about const's
usefulness solely from the information it passes along to the
compiler.
It's a mistaken generalization.
I don't agree. The information passed to the compiler is what the
language standard *guarantees* to be true. So, if you are looking for
guarantees, the information passed to the compiler will be the correct
viewpoint. If you're not looking for guarantees, then you're
looking for
comments, and (theoretically speaking) one comment is as good or
bad as
the next <g>.
Well we'll have to agree to disagree. By the reasoning above, a lot of
type information in C++ is then useless because you can cast it away,
and often in ways that leaves the program well-defined. However, people
do use C++ types to their benefit. I think it's more useful - and
particularly to a "they call me Mr. Compromise" language designer - to
distinguish the "better" nuance of gray instead of insisting that if
it's not black, it's definitely white.
I interpret that to mean that you trust yourself to not subvert const,
even though the Standard allows you to. That is a very reasonable
thing
to do (I also trust myself not to modify arguments without documenting
so in the api <g>). But how is that different from trusting
yourself to
not subvert /*const*/ ? How does that help you in trusting someone
else's code? How does that help you in doing a code review for
security,
robustness, etc.?
Good question. There is a big difference, and I have information here
that I believe could be relevant to you. The difference between const
and /*const*/ is that the former doesn't need much discipline to be
mechanically checkable, while the latter is not.
$ grep const_cast *.cc *.h
$ make
In practice I don't need to really grep (I did it once to collect
supporting data for this thread, with the expected result). In contrast,
D offers me zero in terms of readonly data views. I can never say "oops,
I inserted this cast by accident" because I simply stay away from casts,
but it's very possible that by accident I change some
/*const*/-qualified data. So I see that as a net disadvantage of D.
Yes, I know I'm being pedantic to a fault here.
That has its virtues, but should take us towards capitalizing on that
pedanticism toward building a better const. You seem to drive towards
the conclusion "ah, too messy to be worth implementing" which I think is
exactly the opposite direction from anything useful. I do understand
that as a language author you want to optimize time and energy
investment and commit them to what's really worth doing. My humble
opinion, derived from using C++'s const with all of its imperfections,
is that the concept is well worth it.
But that's a fallacy. Many things don't help the compiler: the "try"
keyword, overloading (polisemy of names), indentation, and (closer to
the point) many aspects of typing.
I don't know what you mean by the 'try' keyword not helping.
How does it help? As far as the compiler cares, this would be enough:
void foo() {
statements1
{
statements2
} catch (T & e) {
statements3
}
statements4
}
"try" is entirely a device for the humans.
As for the
rest, such as indentation, they are a form of commenting, like
/*const*/. I'm not being facetious with /*const*/ - a common practice
with C++ is to use /*in*/, /*out*/, and /*inout*/ comments with
function
parameters. In D, 'in', 'out', and 'inout' are real keywords and
semantically fill the role they suggest. In fact, some language
guarantees even come with them!
That's great. Next step is to add "const" to D and give it guarantees.
A default of immutable data would force you to consider backward
compatibility issues with existing D code. I would love such a
default
nonetheless; I believe it's the right way to go.
There has been some talk in the D newsgroups of doing that, but it has
the potential to be extremely disruptive.
What can I say? Welcome to the club. Ten years from now, a guy called
Walt Brilliant will design a language E and will hang out in D
newsgroups explaining how many design mistakes D has made, and perhaps
how badly D's contracts are implemented... :o)
Andrei
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]