July 09, 2006
Sean Kelly wrote:
> Bruno Medeiros wrote:
>> Derek Parnell wrote:
>>> I'm not from a C++/C#/Java background, so please excuse my lack of understanding about the meaning that is being applied to the term 'const' in these recent discussions.
>>>
>>
>> I think many times people talked a bit vaguely with their meaning of const.
>>
>>> To me, there seems to be two things being talked about.
>>>
>>> (a) Data, which once initialized, is not to be modified for the run-time life of the application.
>>>
>>> (b) Data, which once passed to some function, is not to be modified for the run-time life of that function.
>>>
>>> Walter's proposed refinement of the 'in' keyword does nothing for type (a), and only limited support for type (b), in that it protects data from the called function but not from functions that that subsequently calls. It is only protection for one level deep. And the only data protected is class objects and not other reference types.
>>>
>>> Is there any other types (or subtypes) of 'const' meanings being discussed or considered?
>>>
>>> For example, are we distinguishing between compile-time protection and run-time protection?
>>>
>>
>> 'const', in a general sense, is a mechanism to specify whether a variable/data/object can or can not modified, and enforce that contract (at compile time). 'const' is usually in the sense of (b), that is, some parts of code may modify the data, while others can only read it (thus it is used for ownership management). That's the case for C++.
>> Enforcing the contract means you cannot assign a const variable to a non-const one, or similarly, pass a const variable to a function that expects a non-const argument. The only way to subvert this is with a cast (which should be the only way to subvert anything).
> 
> In the realm of compiler optimization techniques, there's another issue as well: can the compiler assume that, because it is evaluating a const reference, that the underlying data will not change while that reference is in use.  This is the truly sticky part, and is I think a large reason why Walter hasn't settled on anything yet.  For example, consider "const by default":
> 
>     void readWrite( inout T val ) {}
>     void readOnly( in T val ) {}
> 
>     T val;
> 
>     readWrite( inout val );
>     ...
>     readOnly( val );
> 
> In the above, because a mutable reference to val is obtained before readOnly is called, can the compiler assume that the contents of val will not change while readOnly is being evaluated?  Can it ever make that assumption for the entire life of the program after readWrite is called?
> 

Yes, but one has to realize that that is a different thing from the readonly view type of immutability, which is used for ownership management. You can't have 'const' or any other keyword mean both things.
C++'s 'const' has only the meaning of a readonly view type of contract. It does not mean the data cannot change (although in case of a value type, it indeed can't). I recall the discussion between Walter and Alexei where Walter complained that C++'s const was not very useful because it didn't guarantee data was non-changing. Alexei took a while to make Walter understand that that was not the purpose and usefulness of the kind of const/language-construct that he was considering important (which was the readonly view construct).

>> There are some variations in const semantics. In C++, const is a type-modifier, meaning that const can be applied to each type element, and not the "variable as whole". Best to give an example. In C++ you can have:
>>   const int * iptr = ...;
>>   int const * iptr = ...;
> 
> These two are actually identical.  Though things can get a bit tricky if 'int' is replaced by a typedef involving a reference type, which is why the latter form tends to be preferred these days--it is unambiguous, unlike the former form.
> 
>>   const int const * iptr = ...;
>> each with different meanings:
> 
> I believe this is the same as the above, you merely applied the const to int twice.  What you probably meant for these three was:
> 
>     const int * iptr = ...; // mutable ptr to const int
>     int const * iptr = ...; // same as previous line
>     int * const iptr = ...; // const ptr to mutable int
>     const int * const iptr = ...; // const ptr to const int
>     int const * const iptr = ...; // same as previous line
> 

Yes, Deewiant had pointed that out already. ;)

> To return to the typedef issue for a moment, if you do:
> 
>     typedef char* pchar;
> 
>     template<class T> void func( const T val ) {}
> 
>     pchar val = "hello";
> 
>     func( val );
> 
> then it's not entirely clear whether the val in func is a const pointer to mutable data or vice-versa.  Thus the preferred method is:
> 
>     template<class T> void func( T const val ) {}
> 
> Where it's obvious that the 'const' will apply to the pointer if one exists.
> 
> 
> Sean

Another of C++'s subtle trickinesses... I'll keep that in mind, if I have to deal with it in the future.

-- 
Bruno Medeiros - CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
July 09, 2006

Bruno Medeiros wrote:
<snip>
> 
> 
> "However, in D they are one and the same thing - a class member must be declared and defined at the same time."
> Not entirely correct, remember d header files? What happens in D, is that if there is a definition, then there must also be declaration (they're the same actually). But there can be just a definition:
> 
>   class Foo {
>     void func();
>   }
> 
> This means that in D, just as C++, there is no way for the compiler to know in all cases whether the func changes or not the object instance. Thus, it is necessary for the user to specify it.
> 

However, practically speaking, in D (unlike C++) the interface is probably always derived from the actual implementation.
July 09, 2006
Hasan Aljudy wrote:
> 
> 
> Bruno Medeiros wrote:
>> Hasan Aljudy wrote:
> <snip proposal>
>>>
>>> So, what do you think about this proposal?
>>> Is it practical? Does it solve most of the const issues?
>>> Does it even make sense, or is it just stupid all-together?
>>>
> <snip>
>>
>>
>> Indeed, if I understood your proposal correctly, I think it is unpractical, if not down-right senseless. :p
>>
>> Why?
>> Ok, first, what do we want exactly? We want a mechanism that allows us to specify a readonly contract for a variable, that is, declare a variable (or function parameter) that should be a "read-only view" (using Andrei Alexandrescu's term) of another data/object.
> 
> No, if you check my proposal, it was a reply to kris's statement:
> "this whole discussion is basically about array types, since others can happily be passed by value anyway."
> 
> and that is also my understanding.
> 

If that is your premise,then that system would work for it, but I don't agree with such a premise. I have to say I didn't understand Kris's context in the surroundings statements, like the "Using an aggregate (struct or class) instead would give you the /propogation/ aspect required. This is in contrast to Walter's proposal, but requires the use of aggregates rather than, say, an array.", but in any case it seems to me an immutability mechanism is needed for any kind of reference type, like Objects too, not just arrays.
I mean, if I have a function that has an Object parameter and I want to specify and enforce that the Object should not be changed in the function, what am I supposed to do?


>>
>> BTW, Javari is the Java modification described in that paper, which has reference immutability added to the Java language.
>>
> 
> I need to ask .. what did javari *really* add to java?
> Is there something that's impossible with java but possible with javari?
> 
> ..
> ..
> ..
> 
> no?
> I thought so.

Impossible? No, not in the strict sense.
But "better", "more powerful", "more expressive", etc., then yes, in my opinion it does.

Do refrain from using the word "possible" in comparisons between languages. You'll be asking for the typical reply that any Turing complete language can do the same things as any other such language, so we might as well be using Assembler.

-- 
Bruno Medeiros - CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
July 09, 2006

Bruno Medeiros wrote:
> Hasan Aljudy wrote:
> 
>>
>>
>> Bruno Medeiros wrote:
>>
>>> Hasan Aljudy wrote:
>>
>> <snip proposal>
>>
>>>>
>>>> So, what do you think about this proposal?
>>>> Is it practical? Does it solve most of the const issues?
>>>> Does it even make sense, or is it just stupid all-together?
>>>>
>> <snip>
>>
>>>
>>>
>>> Indeed, if I understood your proposal correctly, I think it is unpractical, if not down-right senseless. :p
>>>
>>> Why?
>>> Ok, first, what do we want exactly? We want a mechanism that allows us to specify a readonly contract for a variable, that is, declare a variable (or function parameter) that should be a "read-only view" (using Andrei Alexandrescu's term) of another data/object.
>>
>>
>> No, if you check my proposal, it was a reply to kris's statement:
>> "this whole discussion is basically about array types, since others can happily be passed by value anyway."
>>
>> and that is also my understanding.
>>
> 
> If that is your premise,then that system would work for it, but I don't agree with such a premise. I have to say I didn't understand Kris's context in the surroundings statements, like the "Using an aggregate (struct or class) instead would give you the /propogation/ aspect required. This is in contrast to Walter's proposal, but requires the use of aggregates rather than, say, an array.", but in any case it seems to me an immutability mechanism is needed for any kind of reference type, like Objects too, not just arrays.
> I mean, if I have a function that has an Object parameter and I want to specify and enforce that the Object should not be changed in the function, what am I supposed to do?
> 
> 
>>>
>>> BTW, Javari is the Java modification described in that paper, which has reference immutability added to the Java language.
>>>
>>
>> I need to ask .. what did javari *really* add to java?
>> Is there something that's impossible with java but possible with javari?
>>
>> ..
>> ..
>> ..
>>
>> no?
>> I thought so.
> 
> 
> Impossible? No, not in the strict sense.
> But "better", "more powerful", "more expressive", etc., then yes, in my opinion it does.
> 
> Do refrain from using the word "possible" in comparisons between languages. You'll be asking for the typical reply that any Turing complete language can do the same things as any other such language, so we might as well be using Assembler.
> 

What I meant is .. Java already has one of the most powerfull libraries I've seen (not that I've seen much anyways, mind you).
I was wondering what does javari has to offer that java doesn't? or let me say, what does it add?

When we talk about 'possibilities' in this context, we're not talking about algorithms.

I mean for instance, in the C langauge:

void x( int * p );

It's impossible for the function x to detect whether p points to an array or just a single int. and if it's array, it's impossible to know the size of the array.
July 09, 2006
In article <e8pa25$1ud6$1@digitaldaemon.com>, Hasan Aljudy says...
>
>Bruno Medeiros wrote:
[...]
>> 
>> Plus, your proposal is omissive in many important aspects. For example, how about the transitive property? If I have:
[...]
>you can do what you want with the array reference ..
>when ever you access an element of the array you're getting a copy of
>that element.
>if that element is a pointer, you're getting a copy of the pointer.
>if you don't want this to happen, don't frickin use pointers when you
>don't want others to manipulate your array!!
>

Ok, then how do you pass the common type of char[][] to a function?

Const more than one level deep is necessary in my mind.

I'd recommend that a const reference can't refer to a non const reference. It has the advantage of being simple and easy to understand. Unless this has been shown to not work, I think that it would be informative to try it for a while.

*Question for Walter*: How hard would it be to implement several const models, in parallel (DMD ver 0.162a, 0.163b,...) This would let people try them and see how well they work.

[...]
>
>I need to ask .. what did javari *really* add to java?
>Is there something that's impossible with java but possible with javari?
>
>no?
>I thought so.

Const doesn't make anything new possible, it makes things impossible, and that's the point.


July 10, 2006
Bruno Medeiros wrote:
> Derek Parnell wrote:
> 
>> On Sun, 09 Jul 2006 06:05:11 +1000, Kirk McDonald <kirklin.mcdonald@gmail.com> wrote:
>>
>>
>>
>>> There's another place you can put 'const' in C++:
>>>
>>> class A {
>>>      void bar(int i);
>>>      int foo() const;
>>> };
>>>
>>> This "const" ensures that the member function A::foo does not modify the instance of A that you are calling it on. (If the function does do so, it is a compile error.) This is an issue when you are dealing with const instances of A:
>>>
>>> const A a;
>>>
>>> a.bar(12); // ERROR! a is const, A::bar is not
>>> a.foo();   // Okay
>>>
>>> I actually view this as necessary if we get a way to declare an instance as immutable in D. (Honestly, I have few issues with C++ const, though this "const-by-default for class instances" idea has merit, too.)
>>
>>
>> I can see why this would be a good thing in C++, because the declaration of A::foo() and the definition of A::foo() is not necessarily in the same source file or even written by the same person. This style of 'const' is a way to document a design decision in source code and thus have the compiler enforce the design.
>>
>> However, in D they are one and the same thing - a class member must be declared and defined at the same time. So if the design decision is that A.foo() is not allowed to change any of the data members in an A object, there is no way to get the compiler to know about that design decision. So maybe it would be a useful debugging aid.
>>
>> --Derek Parnell
>> Melbourne, Australia
> 
> 
> "However, in D they are one and the same thing - a class member must be declared and defined at the same time."
> Not entirely correct, remember d header files? What happens in D, is that if there is a definition, then there must also be declaration (they're the same actually). But there can be just a definition:
> 
>   class Foo {
>     void func();
>   }
> 
> This means that in D, just as C++, there is no way for the compiler to know in all cases whether the func changes or not the object instance. Thus, it is necessary for the user to specify it.
> 

Another reason that the compiler can't tell is derived classes.

Additionally, letting the compiler check for const methods would requirer the checking algorithm to be specified by D. Some algorithms will say "go" in the example class is const, some will say it isn't.

class foo
{
	char[] format;

	this(char[] f){ format = f.dup; }	

	char[] go(int i)
	{
		int j;
		char[] f = format;	// f points to member data

		foreach(int k, char c; f)
			if("%" = c)
			{
				j = k;
				break;
			}

		if("%" == f[j])
		{
					// copy f (might not be noticed)
			f = f[0..j+1]~toString(i)~f[j+1..$];

			f[j] = "@";	// assign to f
		}

		return f;
	}
}
1 2 3
Next ›   Last »