Stepping back and looking at constness from another angle.

Derek Parnell derek at nomail.afraid.org
Mon Jun 4 20:19:39 PDT 2007


On Mon, 04 Jun 2007 20:23:41 -0500, Charlie wrote:

> As far as I can tell 'const' is just a guarantee by the person that 
> wrote the function that said function won't modify your variable , and 
> if it tries the compiler won't let it and tell you so.

I also think that the idea of 'stepping back' is a good idea at this point.
And the concept of defining the problem before its solution is also a good
one.

In this case, the problems seem to be ...
(a) How can the source code reader be sure that the data passed to a
function, represented by a parameter, will not have been modified once that
function returns to the caller, and without having access to the function's
source code?
(b) How can a function writer ensure that the compiler will detect or
prevent inadvertent attempts to modify data that was not intended to be
changed by the algorithm designer?

If we assume that the majority of the time, functions are not attempting to
modify passed data then the default, and presumably simpler, syntax should
reflect that passed data is designed to be immutable. Thus it follows that
in order to allow function writers to modify passed data, the parameter
signature explicitly should say that it is permitted. This would make the
code reader's task easier to as the absence of a 'mutable' modifier in the
parameter signature signals a 'safe' function for that parameter. 

Of course, this assumes that the Type of data being passed is potentially
mutable anyway. Given that some data types are by their very nature
immutable, I would suggest that calling a function, which allows changes to
a parameter, with an immutable data type should be a compiler-detected
error. Immutable data types include literals, Walter's new 'slice' type,
invariant types and variables declared as 'final'.

A complication arises with parameters that are references to data rather
than data themselves. In this case we need to be able to independently
specify whether its the reference and/or the data that is allowed to be
changed.

Also, I believe that the type of access permitted to a function needs to be
divorced from the mechanism used to pass the parameter data, as they are
independent concepts.

So what would happen if there was a key word that could be used to specify
that a function has permission to modify a parameter(data)? This key word
would be neither a storage class nor a type, but used solely to grant
permission to a function to change passed data.

For the sake of this discussion, I'll use 'upd' to represent the key word
above but it could be anything better.

  // For reference types (such as classes and variable-sized arrays) ...
  foo(RT c);        // Can't change 'c' or its members
  foo(RT upd c);    // Can change 'c' but not its members
  foo(upd RT c);    // Can't change 'c' but can change its members.
  foo(upd RT upd c);// Can change both 'c' and its members.

  // For value types (which include structs and fixed-size arrays) ...
  foo(VT d);        // Can't change d's contents
  foo(VT upd d);    // Can change d's contents
  foo(upd VT d);    // Can't change d's contents (upd is ignored)
  foo(upd VT upd d);// Can change d's contents (first upd is ignored)

We probably could also cater for the situation in which changes made by a
function are not to be returned to the caller. That is, the function is
given permission to play with the data passed, but any changes it does make
are never returned to the caller. I think this is similar to Walter's
'scope' idea for parameters. However I'd prefer a more specific looking
keyword, such as 'local'.

  foo(local char[] pText); 

This example above permits foo() to modify the data referred to by 'pText'
but not pText itself /and/ ensure that any modifications are not returned
to the caller. This is really just a convenience syntax and is not strictly
required as the function can always just take a local copy of the parameter
data.

With respect to the parameter passing mechanism, I would expect that the
compiler would select the most efficient method given the access, storage
and type information. However, maybe we can let the function writer
override the compiler's selection by using the 'ref' and 'val' key words to
force 'pass by reference' and 'pass by value' respectively. 'ref' would
mean that the function receives the address of the parameter and the
compiler does all the de-referencing as required. In the case of reference
types, the function actually receives the address of a reference and not
the reference itself. 


Well then, how far away from the ideal have I strayed?

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Justice for David Hicks!"
5/06/2007 11:40:15 AM



More information about the Digitalmars-d mailing list