www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Allow const/immutable for normal functions, inner functions and

reply "John Colvin" <john.loughran.colvin gmail.com> writes:
Good idea/bad idea/already done?

int ga = 1;
const int gb = 2;
immutable int gc = 3;

int foo() immutable
{
     // reference to gc is legal
     // any reference to ga or ba is an error
}
int bar() const
{
     // reference to ga, gb and gc is legal
     // cannot modify ga (or gb or gc, obviously)
}

void main()
{
     int a = 1;
     const int b = 2;
     immutable int c = 3;

     int innerFoo() immutable
     {
         // reference to c or gc is legal
         // any reference to a, ga, b or ba is an error
     }
     int innerBar() const
     {
         // reference to a, ga, b, gb c and gc is legal
         // cannot modify a or ga
     }
}

For the inner functions, it's as if the const/immutable is 
applied to the context pointer, the same as it is applied to 
"this" in a class/struct method.

This would be useful because it:
a) provides better control over the exact behaviour of functions 
w.r.t. global/outer state.

b) More importantly: functions/delegates marked immutable can be 
freely shared across threads! This could enable some cool stuff

e.g. this example using an immutable closure to offload work to a 
worker without any explicit handling of input data in the worker 
thread:

auto makeJob(int i, int[] arr)
{
     auto arrImm = arr.idup;
     immutable int iImm = i;

     int[] inner() immutable
     {
         return arr.map!((x) => x % iImm).array;
     }
     return &inner;
}

void worker(Tid tid)
{
     receive(
         (int[] delegate() work)
         {
             tid.send(work());
         }
     );
};

void main()
{
     auto tid = spawn(&worker, thisTid);

     tid.send(makeJob(3, [1,2,3,4,5]));
     receive(
         (int[] data)
         {
             assert(data == [1,2,0,1,2]);
         }
     );
}

All the worker needs to know about its workload is the return 
type of the delegate :) Batteries included!

Note: functions marked immutable are implicitly pure, allowing 
their return values to be implicitly cast to immutable.
Feb 19 2014
next sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Wednesday, 19 February 2014 at 22:20:45 UTC, John Colvin wrote:

 e.g. this example using an immutable closure to offload
That should be
 e.g. this example using a closure marked immutable to offload
Don't want to add any confusion there.
Feb 19 2014
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 02/19/2014 11:20 PM, John Colvin wrote:
 Good idea/bad idea/already done?

 int ga = 1;
 const int gb = 2;
 immutable int gc = 3;

 int foo() immutable
 {
      // reference to gc is legal
      // any reference to ga or ba is an error
 }
 int bar() const
 {
      // reference to ga, gb and gc is legal
      // cannot modify ga (or gb or gc, obviously)
 }
 ...
Does not work as there is no context pointer to qualify and it would add strange limitations to const/... member functions and/or language inconsistencies.
 void main()
 {
      int a = 1;
      const int b = 2;
      immutable int c = 3;

      int innerFoo() immutable
      {
          // reference to c or gc is legal
          // any reference to a, ga, b or ba is an error
      }
      int innerBar() const
      {
          // reference to a, ga, b, gb c and gc is legal
          // cannot modify a or ga
      }
 }

 For the inner functions, it's as if the const/immutable is applied to
 the context pointer, the same as it is applied to "this" in a
 class/struct method.

 This would be useful because it:
 a) provides better control over the exact behaviour of functions w.r.t.
 global/outer state.
 ...
I've brought this up a few times too. This _must_ be done. The current behaviour of DMD is unacceptable here.
Feb 19 2014
prev sibling parent "Meta" <jared771 gmail.com> writes:
On Wednesday, 19 February 2014 at 22:20:45 UTC, John Colvin wrote:
 int ga = 1;
 const int gb = 2;
 immutable int gc = 3;

 int foo() immutable
 {
     // reference to gc is legal
     // any reference to ga or ba is an error
 }
Doesn't pure already do this?
Feb 19 2014