Unofficial wish list status.(Jul 2008)

Jason House jason.james.house at gmail.com
Tue Jul 22 15:36:19 PDT 2008


Walter Bright Wrote:

> Jason House wrote:
> > Walter Bright Wrote:
> > 
> >> Jason House wrote:
> >>> By far, my biggest complaint is that the const system makes only
> >>> one of the following two methods compile.  It forces programmers
> >>> to settle for using global variables to bypass const
> >>> restrictions.  It also touches upon why the purity is required
> >>> when doing multithreading.  I can't fully embrace const until it
> >>> stops encouraging global variables and the gap between purity and
> >>> const is reduced/eliminated.
> >>> 
> >>> =============
> >> logFile log; class foo{ void bar() invariant{
> >>> log.write("Hello World"); } } ============= class Foo{ logFile
> >>> log; void bar() invariant{ log.write("Hello World"); } }
> >>> =============
> >> But the bar() function is not invariant,
> > 
> > That depends on which version of bar you're talking about.  The first
> > bar conforms to the current D standard for invariance.  Everything in
> > class foo remains untouched in the first example, and so bar is
> > invariant.
> 
> True, but it is not pure. Pure functions cannot change global state.
> 
> >> nor can it be pure if it writes things to global state. I am not
> >> sure why bar() needs to be pure, but it *cannot* be pure if it
> >> changes either global state or the state of one of its arguments.
> > 
> > That's exactly right.  So what purpose is declaring bar as invariant
> > serving?
> 
> I don't know why it needed to be marked as invariant (I didn't write it 
> <g>).
> 
> > It's not supporting functional-style multithreading, but
> > wasn't that the point for the const system?
> 
> It is one of the points of the const system. But the idea is not to just 
> declare things invariant and magically they will work in functional 
> style. The idea is that if you want to make something functional, the 
> language will provide support for it if only in the form of telling you 
> when something will not work in functional style. That appears to be the 
> case with bar() - it cannot work in functional style.


Can you answer this more thoroughly?  It's really important to this dialog.  What *other* purposes does the const system serve besides opening the door to functional programming?  I understand that the const system must remain simple to be usable.



> > Since transitive const
> > is already viral, it makes little sense to me that it shouldn't
> > extend to static/global state.  That removes the temptation of
> > programmers to use static/global state to circumvent the const
> > system.  If that's problematic, then IMHO, something must be
> > re-thought because it means people's use of D's const system will not
> > support the functional-style multithreading because people are using
> > it the wrong way.
> 
> The missing ingredient here is what the 'pure' modifier for functions 
> provides. That is the ability to diagnose attempts to alter global state 
> from within a function that is not supposed to do that. Invariant does 
> not imply pure.


That's actually a very key part to my whole point.  There is very little difference between pure and invariant functions.  Why do we need a concept for both?  Under the assumption that we're adding const to support functional programming, I don't understand the motivation for this difference.

I look at this from the following basic principles:
1. As functional programming / implicit multithreading 
   requires pure functions
2. Pure functions require invariant state (object and global state)
3. Imperative programming requires mutable data
4. const (as defined in D) is required to bridge the gap between
   mutable state and invariant state

In C++, we have const data requiring const functions, and in D we have const (invariant) data requiring const (invariant) functions.  The different being that const (invariant) in D is transitive, yielding something that's closer to truly constant state.  Unfortunately, what D provides isn't enough.

Pure functions requires that any shared data is invariant.  That means both transitive invariance like D currently has plus invariant global state.  The net effect is that D currently contains two concepts - invariant functions and pure functions.  Based on principles 1&2, I can't justify the extra complexity.

What I keep wondering is why don't invariant functions operate like pure functions?  Changing transitive const to include any global state accessed through a function seems quite natural to me.

Additionally, const functions as currently written in D are not always const.  The classic C++ example is a tree data structure where a programmer does this.parent.child.property = 1;  An analgous D example would be global_root.child.property = 1;

If the change I hope to see comes about, this loophole will be closed.

> These concepts are not simple, but there is no way to support shared 
> state in multithreaded programming without understanding those concepts. 
> C++ the language has no concept of these things, and people get into 
> endless trouble with it when misunderstanding things and screwing it up. 
> The C++ language itself is of NO help at all. With D, the idea is to 
> enable the language to help by moving things from convention to law. 
> Completely ignoring the issues, like C++ does, is no solution.

I believe that I understand, and hope my more verbose post above will help convince you of that.  I believe (nievely?) that I have value to add if only I can convince you.  I truly do think what I've outlined is a problem with the D const system.



More information about the Digitalmars-d mailing list