July 15, 2005
In article <db8ocu$2gt5$1@digitaldaemon.com>, David Medlock says...
>
>
>How about just an expression like the following( weird off the top of my head, look at the semantics, not syntax):
>
>
>char[] a = "Some valuable data";
>const( a )
>{
>   func1(a);
>   func2(a);
>}
>
>Then the compiler could do an analysis of the functions which are called in the const-block and warn if functions called within attempt to change the data.
>
>Feasible?
>

I think that is as feasible as doing the 'const' check on an 'in' parameter. The problem in both cases is how 'deep' do you make the check.

>-DavidM
>
>PS.  Curious as to what instances do you think const presents optimizations?

The compiler could pass "value" in params by reference. For example a large struct is passed alot faster by reference.

Also, with the 'immutable' rule, the compiler could then safely load an 'in' param. passed by reference into a register and not worry about another reference to the same data in the same function modifying it (and not storing the change back to memory in the meantime). If the in param is used in a tight loop that alone will make a big difference, but not loading something into a register probably precludes other optimizations as well. Right now this problem keeps optimizations from being done in not only D but C, C++, Java and many others for variables that are never even referenced, but since their *could be* another reference, the optimization(s) can't be done.

This is what I'm assuming and there may be more - Walter would be the one to answer that the best I think.

- Dave


July 15, 2005
Dave wrote:

> In article <db8ocu$2gt5$1@digitaldaemon.com>, David Medlock says...
> 
>>
>>How about just an expression like the following( weird off the top of my head, look at the semantics, not syntax):
>>
>>
>>char[] a = "Some valuable data";
>>const( a )
>>{
>>  func1(a);
>>  func2(a);
>>}
>>
>>Then the compiler could do an analysis of the functions which are called in the const-block and warn if functions called within attempt to change the data.
>>
>>Feasible?
>>
> 
> 
> I think that is as feasible as doing the 'const' check on an 'in' parameter. The
> problem in both cases is how 'deep' do you make the check.
> 

Yes but this (or a similar concept) wouldn't change existing pass-by-value semantics.  The depth cannot reasonably be deeper than in C++, imo.

> 
>>-DavidM
>>
>>PS.  Curious as to what instances do you think const presents optimizations?
> 
> 
> The compiler could pass "value" in params by reference. For example a large
> struct is passed alot faster by reference.
> 

The issue there is something like this:

struct A{ int n };
void func( in A a, inout A a2 )
{
  .. makes several changes to a2 based on a
}

A temp;
func( temp, temp );

This currently works in D, but would not if passed by reference.  This is simply one case, there are probably others.

> Also, with the 'immutable' rule, the compiler could then safely load an 'in'
> param. passed by reference into a register and not worry about another reference
> to the same data in the same function modifying it (and not storing the change
> back to memory in the meantime). 

I would bet this type of register optimization is already done by DMD (unless the variable is synchronized). If so, I would be very surprised if you got even a 5% speedup from adding 'const'.  You also have to be wary of passing pointers(references) all over the place. Intel processors cache-misses are quite expensive, whereas structs are on the stack and are therefore in cache already.

-DavidM

July 15, 2005
"Ben Hinkle" <ben.hinkle@gmail.com> wrote in message news:db8apd$269e$1@digitaldaemon.com...
>> Consider this:
>> // somwhere in class RecordsetView ....
>>
>> Field[] fields = myrecordset.fields;
>>
>> // and in galaxy far, far away....
>>
>> fields.sort; // pretty harmless, isn't it?
>>
>> // and in far future, in other galaxy
>> // on the other side of the Universe
>> // somebody will get big bang in carefully
>> // crafted library.
>>
>> D, you want that?
>
> I'm less worried about this happening in D than in other languages since D emphasizes COW so strongly.

Seems like one more language barrier here.

D as a language does not emphasize anything about COW, not strongly not weakly. Dot. And this is a problem.

D documentation *recommends* to use COW.



July 15, 2005
In article <db8slu$2mfv$1@digitaldaemon.com>, David Medlock says...
>
>Dave wrote:
>
>> In article <db8ocu$2gt5$1@digitaldaemon.com>, David Medlock says...
>> 
>>>
>>>How about just an expression like the following( weird off the top of my head, look at the semantics, not syntax):
>>>
>>>
>>>char[] a = "Some valuable data";
>>>const( a )
>>>{
>>>  func1(a);
>>>  func2(a);
>>>}
>>>
>>>Then the compiler could do an analysis of the functions which are called in the const-block and warn if functions called within attempt to change the data.
>>>
>>>Feasible?
>>>
>> 
>> 
>> I think that is as feasible as doing the 'const' check on an 'in' parameter. The problem in both cases is how 'deep' do you make the check.
>> 
>
>Yes but this (or a similar concept) wouldn't change existing pass-by-value semantics.  The depth cannot reasonably be deeper than in C++, imo.
>
>> 
>>>-DavidM
>>>
>>>PS.  Curious as to what instances do you think const presents optimizations?
>> 
>> 
>> The compiler could pass "value" in params by reference. For example a large struct is passed alot faster by reference.
>> 
>
>The issue there is something like this:
>
>struct A{ int n };
>void func( in A a, inout A a2 )
>{
>   .. makes several changes to a2 based on a
>}
>
>A temp;
>func( temp, temp );
>

That would be part of the immutable rule because in effect temp will be modified after the function returns, which would break the 'immutability contract' whether or not it's passed byval or byref.

Let's say func was a template and instead of passing a struct a user of your library passes an instance of a class; in that case everything would get hosed up and it's inconsistent (templates are supposed to be 'generic'). So, a better solution (I think) regardless of the optimizations would be to make 'in' mean the same thing for structs and classes.

I can see where your example is a case not covered by the 'const' checks made for C++; not sure what the solution would be other than to add the check for simple cases like that, but there is the slippery slope and one of the reasons why the compiler can't (practically, as mentioned elsewhere) guarantee immutability.

>This currently works in D, but would not if passed by reference.  This is simply one case, there are probably others.
>
>> Also, with the 'immutable' rule, the compiler could then safely load an 'in' param. passed by reference into a register and not worry about another reference to the same data in the same function modifying it (and not storing the change back to memory in the meantime).
>
>I would bet this type of register optimization is already done by DMD (unless the variable is synchronized). If so, I would be very surprised if you got even a 5% speedup from adding 'const'.  You also have to be

For value types, yes. But what about for reference types??

With the 'immutable in' idea, the optimization could be done for byref types and value types could then still be passed byref into functions and also use the register optimizations.

>wary of passing pointers(references) all over the place. Intel processors cache-misses are quite expensive, whereas structs are on the stack and are therefore in cache already.
>

In my experience, it's generally way more expensive to be repeatedly making value type copies than the potential cache misses caused by passing things like large structs byref; with immutable in, the compiler would make the decision on whether or not to pass value types byref or byval (I base this on not only my own code, but how often I see 'const [type] &' is used for even small structs in C++ code and how often pointers are used to pass structs in C code).

>-DavidM
>


July 15, 2005
Dave wrote:
> In article <db8slu$2mfv$1@digitaldaemon.com>, David Medlock says...
> 
>>Dave wrote:
>>
>>
>>>In article <db8ocu$2gt5$1@digitaldaemon.com>, David Medlock says...
>>>
>>>
>>>>How about just an expression like the following( weird off the top of my head, look at the semantics, not syntax):
>>>>
>>>>
>>>>char[] a = "Some valuable data";
>>>>const( a )
>>>>{
>>>> func1(a);
>>>> func2(a);
>>>>}
>>>>
>>>>Then the compiler could do an analysis of the functions which are called in the const-block and warn if functions called within attempt to change the data.
>>>>
>>>>Feasible?
>>>>
>>>
>>>
>>>I think that is as feasible as doing the 'const' check on an 'in' parameter. The
>>>problem in both cases is how 'deep' do you make the check.
>>>
>>
>>Yes but this (or a similar concept) wouldn't change existing pass-by-value semantics.  The depth cannot reasonably be deeper than in C++, imo.
>>
>>
>>>>-DavidM
>>>>
>>>>PS.  Curious as to what instances do you think const presents optimizations?
>>>
>>>
>>>The compiler could pass "value" in params by reference. For example a large
>>>struct is passed alot faster by reference.
>>>
>>
>>The issue there is something like this:
>>
>>struct A{ int n };
>>void func( in A a, inout A a2 )
>>{
>>  .. makes several changes to a2 based on a
>>}
>>
>>A temp;
>>func( temp, temp );
>>
> 
> 
> That would be part of the immutable rule because in effect temp will be modified
> after the function returns, which would break the 'immutability contract'
> whether or not it's passed byval or byref.
> 
Unless you eliminate ALL call-by-value then the optimization just isn't possible. You aren't suggesting that are you?

-DavidM


July 15, 2005
>> Compiler will check function for immutable violations.
>
> It is easy to say, try to describe such "check".

I have done so several times, with several different ideas.

>>> One unknown programmer to other unknown programmer?
>>
>> The programmer of the function will guarantee it, the compiler will enfore
>> it.
>
> How?
>
> class Recordset
> {
>     Field[] fields() { ... } // supposed to be readonly

Then you need to label it as such. Either 'readonly', 'const', etc.

>     Value[] values() { ... } // may be readonly, may be not

Not possible, make up your mind.

> }
>
> static Field f;
>
> bool Foo( in Recordset rs )
> {
>     rs.fields[0].foo();
>     rs.values[0].bar();
>     f = rs.fields[0];
> }
>
> Given Foo example above try to describe
> what needs to be done by compiler to
> verify immutability of rs parameter.

The same way C++ const does it.

Regan
July 15, 2005
In article <db95ut$2u1i$1@digitaldaemon.com>, David Medlock says...
>
>Dave wrote:
>> In article <db8slu$2mfv$1@digitaldaemon.com>, David Medlock says...
>> 
>>>Dave wrote:
>>>
>>>
>>>>In article <db8ocu$2gt5$1@digitaldaemon.com>, David Medlock says...
>>>>
>>>>
>>>>>How about just an expression like the following( weird off the top of my head, look at the semantics, not syntax):
>>>>>
>>>>>
>>>>>char[] a = "Some valuable data";
>>>>>const( a )
>>>>>{
>>>>> func1(a);
>>>>> func2(a);
>>>>>}
>>>>>
>>>>>Then the compiler could do an analysis of the functions which are called in the const-block and warn if functions called within attempt to change the data.
>>>>>
>>>>>Feasible?
>>>>>
>>>>
>>>>
>>>>I think that is as feasible as doing the 'const' check on an 'in' parameter. The problem in both cases is how 'deep' do you make the check.
>>>>
>>>
>>>Yes but this (or a similar concept) wouldn't change existing pass-by-value semantics.  The depth cannot reasonably be deeper than in C++, imo.
>>>
>>>
>>>>>-DavidM
>>>>>
>>>>>PS.  Curious as to what instances do you think const presents optimizations?
>>>>
>>>>
>>>>The compiler could pass "value" in params by reference. For example a large struct is passed alot faster by reference.
>>>>
>>>
>>>The issue there is something like this:
>>>
>>>struct A{ int n };
>>>void func( in A a, inout A a2 )
>>>{
>>>  .. makes several changes to a2 based on a
>>>}
>>>
>>>A temp;
>>>func( temp, temp );
>>>
>> 
>> 
>> That would be part of the immutable rule because in effect temp will be modified after the function returns, which would break the 'immutability contract' whether or not it's passed byval or byref.
>> 
>Unless you eliminate ALL call-by-value then the optimization just isn't possible. You aren't suggesting that are you?
>
>-DavidM
>

No - compiler decides.

The reason the optimization isn't done on byref params in C or C++ is not because it can't be done, but because it might produce unexpected results if someone happens to write code like your example (among others). It's not a question of computer science, it's a question of the rules of the language.

So, if 'in' is changed to to be 'immutable' then cases like your example would not be legal, so the optimization could then be done on params. passed by reference.

A lot of Fortran compilers already do these optimizations on parameters passed byref. In a case like your example, the rule in Fortran is basically "don't do that" but it is not required to be enforced by Fortran compilers.

What this thread has been discussing lately is about changing the rules for D 'in' params. to make them 'immutable' inside the function and enforcing that somehow. A side-effect of having these 'readonly' params. would be the chance to legally use these Fortran-like optimizations in D on anything passed by-whatever. The goal would be to forget worrying about how the compiler chooses to pass an 'in' parameter w/o creating a bunch of hard-to-find bugs.


July 15, 2005
"Regan Heath" <regan@netwin.co.nz> wrote in message news:opsty7jlu423k2f5@nrage.netwin.co.nz...
>>> Compiler will check function for immutable violations.
>>
>> It is easy to say, try to describe such "check".
>
> I have done so several times, with several different ideas.
>
>>>> One unknown programmer to other unknown programmer?
>>>
>>> The programmer of the function will guarantee it, the compiler will
>>> enfore
>>> it.
>>
>> How?
>>
>> class Recordset
>> {
>>     Field[] fields() { ... } // supposed to be readonly
>
> Then you need to label it as such. Either 'readonly', 'const', etc.
>
>>     Value[] values() { ... } // may be readonly, may be not
>
> Not possible, make up your mind.
>
>> }
>>
>> static Field f;
>>
>> bool Foo( in Recordset rs )
>> {
>>     rs.fields[0].foo();
>>     rs.values[0].bar();
>>     f = rs.fields[0];
>> }
>>
>> Given Foo example above try to describe
>> what needs to be done by compiler to
>> verify immutability of rs parameter.
>
> The same way C++ const does it.

I lost you here....
Are you proposing to mark all immutable methods and references by
const/readonly
as in C++?








July 16, 2005
Hi,

>> That would be part of the immutable rule because in effect temp will be modified after the function returns, which would break the 'immutability contract' whether or not it's passed byval or byref.
>> 
>Unless you eliminate ALL call-by-value then the optimization just isn't possible. You aren't suggesting that are you?

Just out of curiosity, what if this was actually done? Does it cause some sort of great evil?

Some assumptions:
1) Most parameters are "in," therefore semantically readonly.
I think this is one of the main points of the whole const/immutable debate.
2) Passing by reference is more efficient for everything except maybe int.
The vast majority of C code I've seen passes structs by pointer, even if just
something like struct Point { int X, Y; }.

So then, what if all parameters are passed by reference, with the additional requirement that they be made readonly. What are the problems with this (not saying there aren't)?

Plus, there is the added benefit of that optimization you mentioned, so it would be even more efficient.

--AJG.


July 16, 2005
I would like to return to basics again.

I. Readonly variable.

What is readonly parameter or variable?

readonly (c++::const) something means that in given scope any write-over operations are disabled for such variable.

*given scope* - means not only function body but also
the whole application domain if e.g. such variable is static
or member field of some class. Generally speaking
such variable has type having operator= and the like
disabled.

readonly variable does not mean that variable will not be changed. Such variable is an alias of some memory location - it just means that using this particular alias it is imposible to overwrite that memory location.

II. Immutable variable.

What is 'immutable' or 'immutable in' then?
Abstract meaning of immutable variable - snapshot of data under
this variable. Immutability of function parameter is a gurantee
that in the scope of this function any two consequent readings
of any data location reachable from this var will lead to the same
result.  This apply to function parameters and other variables e.g.
member field of some class.

III. 'in' parameter in current version.

Currently 'in' parameter is a copy (shallow snapshot) of some value passed to the function. 'in' parameter variable is an alias of stack location. By now it is *mutable* variable.

IV. readonly arrays and pointers. Implementation.

My initial proposal is not about immutability. It is about
readonly versions of two primitive reference types.
Not more not less. Implementation of this types
is simple, feasible and verifiable by compiler 100% of cases
theoretically and practically. Implementation of such two
types is pretty much mechanical process similar to modification
of static type table.

V. Implementation of 'in immutability'.

Let's take a look on possible immutability implementations:
We are considering only non-intrusive implementations here,
i.e. impementations without readonly/const tags of variables
and methods. As such tags are known to produce
"clutter", (c) Walter and others.

  V.1. Snapshot.
         Snapshot as a process, also known as 'marshalling',
         used in RPC implementations (e.g. in COM/CORBA)
         to pass parameters across process/machine
         boundaries. Demands synchronized access to passing
         value and all values reachable from it.
         Practically is not feasible to be short.

  V.2. GC-like scan against passing variable.
         Don't need too much comments here.
         In fact V.1. is a form of GC too.
         Copying GC this time.

Here is the first question: So, how is
this beaitiful "immutable in" supposed to
be implemented?

And here is the second question:
Can anybody provide *realistic* example of some
practical task where such "immutable in" is the must?
I will greatly appreciate if this example will not
be reasonably reproducible with readonly arrays/pointers
and use of access attributes for other types.

---------------------------
Andrew Fedoniouk.
http://terrainformatica.com