Stepping back and looking at constness from another angle.

Johan Granberg lijat.meREM at OVEgmail.com
Tue Jun 5 03:12:34 PDT 2007


David B. Held wrote:

> Let me point out a few guiding principles that are worth considering:
> 
> 1) The more code you break, the more benefit you must offer
> 
> 2) Orthogonality is good; exceptions and corner cases bad
> 
> While the idea of making const the default sounds appealing, why limit
> it to function parameters?  Why not treat variables as const-by-default
> also?  Very functional indeed.  Unfortunately, not very D-like.  D could
> have builtin lists, just like functional languages.  Instead, it has
> arrays.  Guess why?  Arrays are smaller and faster.  D chooses
> performance.  Those arrays could be immutable by default, but they
> aren't.  Why not?  Try to time the performance of quicksort in Haskell,
> and compare it to C's qsort(), and you will soon understand the power of
> mutable arrays.  Haskell's version certainly looks better, but C's burns
> the pants off all takers, because it's about as fast as hand-coded,
> fully optimized, no-holds-barred assembly.
> 
> D is a multi-paradigm language, like C++, but let's not forget that
> "imperative" is a paradigm, and that machine language itself is
> imperative.  And since D aims to let you get as close to the machine as
> possible, it makes sense that the default for *variables* is mutability.
> 
> A corollary to principle 2) above is:
> 
> 3) Function parameters should have the same syntax as local declarations
> 
> Why?  Well, why not?  Why should users have to think hard about whether
> a particular syntax is only legal for parameters or not?  While certain
> qualifiers like 'in' and 'out' must necessarily be exceptions, they idea
> is that they provide sufficient convenience to justify their existence.
>   Beyond that, you should be able to look at a function parameter list
> and say: "Each of those parameter declarations could be pulled out into
> a local declaration".
> 
> If we agree that is a powerful principle that makes the language easier
> to understand, then we see why it is not acceptable for function
> arguments to default to const while locals do not.  And if we agree that
> D is an imperative language before all else, because it is a *systems*
> language, then we see why it is not acceptable for locals to default to
> const.  This leads us to conclude that mutability should indeed be the
> default, and that constness should be indicated explicitly.  However, I
> think 'in' as a synonym for constness is a very nice compromise that
> gives just about the shortest possible abbreviation for 'const' that you
> could imagine (short of something silly like type sigils).
> 
> One person mentioned that Perl doesn't have 'const'.  In fact, that is
> only half-true.  There is a Perl pragma called 'constant' which is used
> like thus:
> 
> use constant PI => 3.14159;
> 
> Unfortunately, being a pragma, the symbol PI does not interpolate like a
> scalar, making certain uses of it very awkward.  Larry recognized both
> that this was unacceptable and that constants are indeed very useful,
> and decided to give Perl 6 first-class constants.
> 
> Also, Andrei likes to make much of the fact that Perl, like Java, has
> immutable strings.  Who would have guessed?  Perl is pretty much the
> poster child of string manipulation and obscure do-anything code
> semantics, so unless you went looking for it, very few people would
> guess that strings in Perl are actually immutable, but they are.  Why is
> that?  Well, it's because making strings CONST makes it very easy to
> guarantee that there is no improper aliasing mixed with string mutation.
> 
> Java programmers that need mutable strings use StringBuilder, and then
> convert to a String when they're done.  It's such a powerful idiom that
> the xxxBuilder pattern is quite popular in the Java standard library
> now.  How could D get immutable strings?  Well, we could try it with
> const, but if you look closely, 'const' doesn't mean "this array can't
> change".  It means: "You can't change this array through this const
> reference, but somebody else can."  That is, 'const' isn't strong enough
> to get you immutable strings.  For that, you need something stronger.
> You need 'invariant'.  Only invariant guarantees that nobody holds a
> mutable reference to your object, and thus, you are free to alias the
> object all you like, quite safely.  D, being a *systems language*,
> concerned with *performance*, will take any performance-enhancing
> substance available, and 'invariant' is one of the best drugs on the
> market (eat your heart out, Floyd).
> 
> So could we live with 'invariant' and dump 'const'?  Well, we could, but
> it wouldn't result in a very useful language.  Because then we wouldn't
> be able to say: "I want the implementor of this function to have a
> read-only view on my precious mutable data which I need to be able to
> update in place."  The only way you could do that is to make a copy,
> which defeats the whole point of 'invariant'.  Are things starting to
> become a little more clear?
> 
> So if we agree that the Functional Paradigm is A Good Thing, and part of
> why it's a good thing is Purity, then it follows that D can gain some of
> the benefits of FP by implementing limited purity, which is what
> const/invariant are.  Why is purity a good thing?  It's very simple.
> Functions, in the mathematical sense of a map from A to B, are fairly
> easy to understand.  State machines, on the other hand, are much much
> harder to understand.  Adding variables to a state machine typically
> increases the number of states geometrically, and the number of state
> transitions exponentially.  Adding constants, on the other hand, does
> not increase the number of states, nor the number of transitions, which
> means that you literally get an exponential increase in simplicity by
> making as many things immutable as possible.  And that's why 'const' in
> general is A Good Thing(TM).
> 
> Of course, the cost of all this is some additional syntactic burden.
> But consider the opposite case: pure functional languages trying to
> implement mutable state.  In our case, we only need to sprinkle a
> keyword here and there.  For Haskell, you need to *define a Monad*.  In
> case you didn't know, a Monad is a structure with three distinct
> operations which are fairly non-trivial for a novice to define.  On the
> other hand, most novices can add 'const' to a declaration without any
> assistance whatsoever.  This is most likely why even most functional
> languages are not pure.
> 
> If you think that you are willing to take the plunge and make all your
> programs const by default, consider all the libraries that D can and
> does link to, and consider the effect of const-by-default on that
> codebase.  Even if you are willing to use a Haskell-like discipline
> yourself, most D code is not, and would take a huge effort to fix up.
> 
> One final observation is this: the benefit of const is something of an
> emergent property that is sensitive to scale.  That is, for small
> programs, the cost outweighs the benefit.  But as a program grows from a
> few modules to several libraries and tens or hundreds of modules with
> many thousands of lines of code written by teams of programmers, the
> benefit of const pays back its cost through every possible interaction
> of programmers.  Why is that?  It's because 'const' is both
> documentation and a promise.  It tells another programmer what to
> expect, and it promises to follow through on that created expectation.
> Since the number of possible interactions among programmers is factorial
> (super-exponential!) in the number of coders, the benefit of const soon
> becomes apparent with even a modestly-sized team.
> 
> If you have reservations about const on your personal project, try to
> imagine writing a very large project with a group and ask yourself how
> much you trust the other programmers (imagine the group stepped out of
> Dilbert, and not your favorite startup).  While inferring 'const' is
> certainly possible (and several papers have been written about how to do
> it), it neglects the documentation aspect of 'const'--the contractual
> aspect of it.  This is something that only becomes apparent at large
> scales, but once you reach those scales, it becomes very visible very
> quickly.
> 
> If there is some magic const-bullet that would make everyone happy, I'm
> sure Walter is the first person in the D community that wants to know
> about it.  Unfortunately, this is a very hard problem, and solutions to
> hard problems always involve some kind of compromise.  Of course, the
> problem with compromises is that they are guaranteed to piss off
> everyone at least a little bit (look at immigration reform for a good
> example).  That doesn't mean it isn't a good compromise; on the
> contrary, it probably means it is.
> 
> Dave

You write a loot about Haskell and how awkward it is to use pure functional
constructs in a systems language like D. But I have not heard anyone say
that they want to make D pure in any way. Even functional languages like
Standard ML have reference parameters (mutable) and arrays (also mutable)
and what was suggested for D was even less extream, if you are OK whit
writing const all over the place how can writing mutable all over the place
be any worse. The idea is that if you forget to declare something const the
compiler cant catch you but if you forget to declare mutable the compiler
will complain if you try to change it. I don't know about your programs but
when I code in imperative languages like C D or Java most variables are
never changed they are defined locally as the result of some computation or
function call and read one ore more time during the rest of the function,
granted globals and class members are a little different but I don't think
they are more common than function parameters and if you are OK whit
writing const next to each function parameter writing mutable next to some
member variables should not be a huge burden.



More information about the Digitalmars-d mailing list