July 03, 2005
"AJG" <AJG_member@pathlink.com> wrote in message news:da7vvd$lm6$1@digitaldaemon.com...
> >Yet the value can change anyway. Another reference can change it, and another thread can change it. It isn't "constant" at all, and cannot be relied on to be constant, even if your program is 100% "const-correct".
The
> >C++ const is *completely useless* to the compiler optimizer for that
reason.
>
> I can't fathom that the compiler can't make use of the fact that you are
telling
> it: "The following function body will not modify [variable] at all,
ever."?

Consider the following C++ function:

    int foo(const int *p, int *q)
    {
        int i = *p;
        *q = 3;
        return *p;
    }

At the return statement, could we replace *p with i, thereby saving ourselves a dereference operation? After all, p points to "const" data, right? Wrong. Consider calling foo() this way:

    int a[3];
    ...
    foo(a, a);

Since p and q now hold the same value, *q = 3; will change the contents of what p points to.

This code is perfectly legal C++, and is "const-correct". It happens often enough in real code, too, as I discovered when trying to implement this optimization.


July 03, 2005
"Andrew Fedoniouk" <news@terrainformatica.com> wrote in message news:da7ulp$kub$1@digitaldaemon.com...
> ooohh... could you first provide me an option to *declare* e.g. slice as immutable thus I'll be able to return it from function without duping it? *That* would be optimization.

In following COW principles, you do not need to dup the slice when returning it. The producer of the value doesn't need to dup it, the *consumer* does, and only if the *consumer* modifies it. Taking a slice of an array does not modify it in any way, so no dup is required.

So I am not understanding why const or immutable is needed for D strings. I've written a number of string processing programs in D (including a macro text processor, and the silly program that transforms newsgroup postings into the "archive" pages), and didn't have any difficulty with D strings. They went together with much less effort and far fewer bugs than their C++ counterparts.


> Walter, again, what language are you going to substitute
> by D? What is the main target? C/C++?
> If yes then they have const references.
> If Java or C# then show how to implement String in D
> and very desireable with slices - they are extremely useful
> and are making D so attractive (among other good and
> useful features).
>
> Again, in my opinion
> 1) const references - const arrays and pointers
> 2) opAssign/dtors in structures
> are the *only* things left in D not-implemented from
> C++ feature set. If they will be there you and anyone
> can honestly say "D is next letter after C and C++" as
> it allows you to do *everything* that you can in C++
> and it has much more "well done" features - true next step.

Unfortunately, there are several other "must haves" various people want D to have.

I do understand the desire for const. But there are many different ways to approach the problem, and I'm not willing to just duplicate the C++ const with all its weaknesses and problems. There's got to be a better way.


July 03, 2005
Walter wrote:

> So I am not understanding why const or immutable is needed for D strings.
> I've written a number of string processing programs in D (including a macro
> text processor, and the silly program that transforms newsgroup postings
> into the "archive" pages), and didn't have any difficulty with D strings.
> They went together with much less effort and far fewer bugs than their C++
> counterparts.

No offense, but didn't you design the language and string handling ? :-)

I've written several segfaults by changing "readonly" literals, and
gotten some strange results by setting hash string keys without duping them first (and then later changing the value of the string, that is...)
I also think it's pretty easy to "mess up" when using any array slices.

It would be great if there were some "extra mechanism" enforcing CoW.

> I do understand the desire for const. But there are many different ways to
> approach the problem, and I'm not willing to just duplicate the C++ const
> with all its weaknesses and problems. There's got to be a better way.

It would nice to come up with an approach that would:
a) default local strings/arrays to read-write
b) default external parameters to read-only

"in"/"out" doesn't really work, since it only affects the array
pointer/length and not the actually characters. Maybe something
like "char[out] string", but that looks a little like a variable...

Anyway, I wouldn't want to see "const" (or "readonly", "immutable")
all over the place either - better to have a "readwrite" or "mutable"
keyword for the (few?) cases when you *do* want to modify the contents ?


I guess it's the D Gentlemen's Agreement, while keeping on searching.
(it's easy enough* to implement java.lang.String and StringBuffer in D,
but I'm still hoping there is some compromise between "C" and "Java")

--anders

* PS. Here's one such hack (mostly for the discussion really)
http://www.algonet.se/~afb/d/dcaf/html/class_string.html
http://www.algonet.se/~afb/d/dcaf/html/class_string_buffer.html
July 03, 2005
In article <da8but$t3j$1@digitaldaemon.com>, =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= says...
>
>
>I guess it's the D Gentlemen's Agreement, while keeping on searching. (it's easy enough* to implement java.lang.String and StringBuffer in D, but I'm still hoping there is some compromise between "C" and "Java")
>
>--anders
>
>* PS. Here's one such hack (mostly for the discussion really) http://www.algonet.se/~afb/d/dcaf/html/class_string.html http://www.algonet.se/~afb/d/dcaf/html/class_string_buffer.html


For what it's worth, that String isn't immutable in Java/C# sense, is it? Every time you hand out a char[], you give the caller a reference to your internal member. Should be a "return str.dup;" :-(

Best regards,
Stefan


July 03, 2005
Stefan Zobel wrote:

> For what it's worth, that String isn't immutable in Java/C# sense, is it?
> Every time you hand out a char[], you give the caller a reference to your internal member. Should be a "return str.dup;" :-(

This goes for most implementations of toString(), I guess ?
This actually would be the key issue we are debating here...

The char[] that is given out *is* read-only, there's just no
way of indicating that - except for the Gentlemen's Agreement.


And, no, it should NOT be a dup (as my "StringBuffer" did do that).
It's _supposed_ to return a reference to the (immutable) contents.

And you could still peek and poke it by casting to char* and
changing the memory inside, but that's besides the point here.


I don't think that D needs a string class, but "something else" ?
(as in Java and C#, the class internals are protected by the VM)

I like the current strings, it's just that they are (or: could be)
a little dangerous - just like a raw char* in C could be, I guess.


But for C/C++ there is "const" - D needs something similar, but better.

--anders
July 03, 2005
"Walter" <newshound@digitalmars.com> wrote in message news:da6k71$11rs$1@digitaldaemon.com...
>
> "Ben Hinkle" <bhinkle@mathworks.com> wrote in message news:da4afr$24jc$1@digitaldaemon.com...
>> How would this cover the following case that Walter's proposal covers:
>> class A { int x; }
>> void foo(in A obj){
>>   int y = obj.x;
>>   // do whatever you want...
>>   assert( obj.x == y );
>> }
>> void main() {
>>   A obj = new A;
>>   foo(obj); // says it doesn't change obj
>> }
>> Is it practical to force A to implement some immutability just because
>> foo
>> doesn't change its inputs? I'm not saying Walter's proposal is prefect.
> It's
>> very strong for foo to say no other thread or reference will change obj since it has no control over what other threads are doing. I would be
> taking
>> pretty much blind leap of faith when declaring an object reference as
>> 'in'
>> and saying that no other thread is stepping on that object during the
>> call
>> lifetime.
>
> You're right. I have misgivings about it for that reason.
>
> On the other hand, look at C++ "const". Nothing about "const" says that
> some
> other thread or reference cannot change the value out from under you at
> any
> moment. Furthermore, it can be cast away and modified anyway. The semantic
> value of C++ "const" is essentially zip. This is why I am often flummoxed
> why it is given such weight in C++.
>

It is equally probable that another thread could step on obj within the foo() call lifetime as it is now, regardless of any optimizations that the "in" proposal allows, so I don't think that concern should be a show stopper. Either way the results are the same - sporadically incorrect results, and either way it is going to be a bear to debug and proper synchronization by the /user/ of obj and foo() will be the way to fix the problem - same as any other multi-threading issue.

I see no problem with just removing the part of the proposal that promises that no other /thread/ will change obj. because I don't think that is practical in any sense at the language implementaton level for a language with the goals of D (D doesn't offer or promise auto-synchronization in any other case, does it?).

- Dave


July 03, 2005
"Dave" <Dave_member@pathlink.com> wrote in message news:da8nqk$161t$1@digitaldaemon.com...
>
> "Walter" <newshound@digitalmars.com> wrote in message news:da6k71$11rs$1@digitaldaemon.com...
>>
>> "Ben Hinkle" <bhinkle@mathworks.com> wrote in message news:da4afr$24jc$1@digitaldaemon.com...
>>> How would this cover the following case that Walter's proposal covers:
>>> class A { int x; }
>>> void foo(in A obj){
>>>   int y = obj.x;
>>>   // do whatever you want...
>>>   assert( obj.x == y );
>>> }
>>> void main() {
>>>   A obj = new A;
>>>   foo(obj); // says it doesn't change obj
>>> }
>>> Is it practical to force A to implement some immutability just because
>>> foo
>>> doesn't change its inputs? I'm not saying Walter's proposal is prefect.
>> It's
>>> very strong for foo to say no other thread or reference will change obj since it has no control over what other threads are doing. I would be
>> taking
>>> pretty much blind leap of faith when declaring an object reference as
>>> 'in'
>>> and saying that no other thread is stepping on that object during the
>>> call
>>> lifetime.
>>
>> You're right. I have misgivings about it for that reason.
>>
>> On the other hand, look at C++ "const". Nothing about "const" says that
>> some
>> other thread or reference cannot change the value out from under you at
>> any
>> moment. Furthermore, it can be cast away and modified anyway. The
>> semantic
>> value of C++ "const" is essentially zip. This is why I am often flummoxed
>> why it is given such weight in C++.
>>
>
> It is equally probable that another thread could step on obj within the foo() call lifetime as it is now, regardless of any optimizations that the "in" proposal allows, so I don't think that concern should be a show stopper. Either way the results are the same - sporadically incorrect results, and either way it is going to be a bear to debug and proper synchronization by the /user/ of obj and foo() will be the way to fix the problem - same as any other multi-threading issue.
>
> I see no problem with just removing the part of the proposal that promises that no other /thread/ will change obj. because I don't think that is practical in any sense at the language implementaton level for a language with the goals of D (D doesn't offer or promise auto-synchronization in any other case, does it?).
>
> - Dave

You're right - the threading model shouldn't enter into it. I'm liking Walter's suggestion more now. Earlier I thought it was too strong a condition but now I can see, for example, lots of places in phobos where 'in' can be used.


July 03, 2005
In article <da88rb$ruj$1@digitaldaemon.com>, Walter says...
>
>
>"AJG" <AJG_member@pathlink.com> wrote in message news:da7vvd$lm6$1@digitaldaemon.com...
>> >Yet the value can change anyway. Another reference can change it, and another thread can change it. It isn't "constant" at all, and cannot be relied on to be constant, even if your program is 100% "const-correct".
>The
>> >C++ const is *completely useless* to the compiler optimizer for that
>reason.
>>
>> I can't fathom that the compiler can't make use of the fact that you are
>telling
>> it: "The following function body will not modify [variable] at all,
>ever."?
>
>Consider the following C++ function:
>
>    int foo(const int *p, int *q)
>    {
>        int i = *p;
>        *q = 3;
>        return *p;
>    }

>    int a[3];
>    ...
>    foo(a, a);

Hm... that's an interesting situation. Ok, say pointers are not considered, because they are inherently unsafe anyway. Let's take only regular in/out/inout variables. Could the same trick be done simply with these?

>This code is perfectly legal C++, and is "const-correct". It happens often enough in real code, too, as I discovered when trying to implement this optimization.

It's possible that such code, although legal, is simply bad code that can't be protected against. The function documentation should state which variables shouldn't be the same. I think it's simply undefined behaviour.

I dunno if all optimization should be off simply because of the occasinal badly coded, documented and used function.

It's kind of like modifying the iterating array inside a foreach - perfectly valid too, but that's going to be ugly (perhaps that should be made illegal too, btw). Or for example, sending the same variable to multiple parameters of a string-manipulation (str*) function. Consider this:

// char *str = "Some text";
// str = strcat(str, str);

---------------------------

Once again, what if pointers are not considered, would this make things easier? If you take out pointers, couldn't the compiler detect if you were sending the same variable to multiple differently-accessable parameters?

Cheers,
--AJG.


July 03, 2005
"Ben Hinkle" <ben.hinkle@gmail.com> wrote in message news:da8qa5$17op$1@digitaldaemon.com...
>
> "Dave" <Dave_member@pathlink.com> wrote in message news:da8nqk$161t$1@digitaldaemon.com...
>>
>> "Walter" <newshound@digitalmars.com> wrote in message news:da6k71$11rs$1@digitaldaemon.com...
>>>
>>> "Ben Hinkle" <bhinkle@mathworks.com> wrote in message news:da4afr$24jc$1@digitaldaemon.com...
>>>> How would this cover the following case that Walter's proposal covers:
>>>> class A { int x; }
>>>> void foo(in A obj){
>>>>   int y = obj.x;
>>>>   // do whatever you want...
>>>>   assert( obj.x == y );
>>>> }
>>>> void main() {
>>>>   A obj = new A;
>>>>   foo(obj); // says it doesn't change obj
>>>> }
>>>> Is it practical to force A to implement some immutability just because
>>>> foo
>>>> doesn't change its inputs? I'm not saying Walter's proposal is prefect.
>>> It's
>>>> very strong for foo to say no other thread or reference will change obj since it has no control over what other threads are doing. I would be
>>> taking
>>>> pretty much blind leap of faith when declaring an object reference as
>>>> 'in'
>>>> and saying that no other thread is stepping on that object during the
>>>> call
>>>> lifetime.
>>>
>>> You're right. I have misgivings about it for that reason.
>>>
>>> On the other hand, look at C++ "const". Nothing about "const" says that
>>> some
>>> other thread or reference cannot change the value out from under you at
>>> any
>>> moment. Furthermore, it can be cast away and modified anyway. The
>>> semantic
>>> value of C++ "const" is essentially zip. This is why I am often
>>> flummoxed
>>> why it is given such weight in C++.
>>>
>>
>> It is equally probable that another thread could step on obj within the foo() call lifetime as it is now, regardless of any optimizations that the "in" proposal allows, so I don't think that concern should be a show stopper. Either way the results are the same - sporadically incorrect results, and either way it is going to be a bear to debug and proper synchronization by the /user/ of obj and foo() will be the way to fix the problem - same as any other multi-threading issue.
>>
>> I see no problem with just removing the part of the proposal that promises that no other /thread/ will change obj. because I don't think that is practical in any sense at the language implementaton level for a language with the goals of D (D doesn't offer or promise auto-synchronization in any other case, does it?).
>>
>> - Dave
>
> You're right - the threading model shouldn't enter into it. I'm liking Walter's suggestion more now. Earlier I thought it was too strong a condition but now I can see, for example, lots of places in phobos where 'in' can be used.

I think Walter's idea is a great idea and a good compromise!

Truth be told, I actually think the following would be the best:

[none]/in/out/inout - [none] and 'in' would follow the new proposal with regard to 'immutable', and /all/ would allow the new opimizations that I think Walter has in mind. The exceptions would be pointer params. and functions declared extern or exported, which would simply operate as they do now, where the expectation is that they are treated differently anyway.

volatile/volatile in/volatile out/volatile inout - 'volatile', 'volatile in', 'volatile out' and 'volatile inout' params. would basically operate exactly as they do now. Just like other statements in any other scope, a "volatile" param. would mean "inhibit optimizations on the variable that may effect memory reads/writes". Not even a new keyword..

The whole justification for these new defaults is because the cases where "volatile" would have to be used for the code to operate correctly are a small minority, so shouldn't the default go with what benefits the great majority of cases?

Also, the same justification goes for making the default [none] and 'in' operate the same way w.r.t. the new proposal - majority of cases rules. Another big plus would be not having to litter code with 'in' (like C++ code is littered with 'const').


July 03, 2005
"Walter" <newshound@digitalmars.com> wrote in message news:da88rb$ruj$1@digitaldaemon.com...
>
> "AJG" <AJG_member@pathlink.com> wrote in message news:da7vvd$lm6$1@digitaldaemon.com...
>> >Yet the value can change anyway. Another reference can change it, and another thread can change it. It isn't "constant" at all, and cannot be relied on to be constant, even if your program is 100% "const-correct".
> The
>> >C++ const is *completely useless* to the compiler optimizer for that
> reason.
>>
>> I can't fathom that the compiler can't make use of the fact that you are
> telling
>> it: "The following function body will not modify [variable] at all,
> ever."?
>
> Consider the following C++ function:
>
>    int foo(const int *p, int *q)
>    {
>        int i = *p;
>        *q = 3;
>        return *p;
>    }
>
> At the return statement, could we replace *p with i, thereby saving ourselves a dereference operation? After all, p points to "const" data, right? Wrong. Consider calling foo() this way:
>
>    int a[3];
>    ...
>    foo(a, a);
>
> Since p and q now hold the same value, *q = 3; will change the contents of what p points to.
>
> This code is perfectly legal C++, and is "const-correct". It happens often enough in real code, too, as I discovered when trying to implement this optimization.

Walter, it is enough for me to know that

int foo(const int *p, int *q)
   {
       int i = *p;
       *q = 3;

       .... 200 lines of code

       return *p;
   }

will not change *p. I am not asking for optimization here. Optimization happened before - when I wrote this fucntion declaration using const parameters.

I understand that you focused on optimiziation as compiler and codegenerator writer. This is perfectly good and thank you for that.

But const is a matter of language design and not about optimization. Well not exactly as if I will write both:

int foo(const int *p, int *q)
int foo(int *p, int *q)

then I will make an act of optimization on the design level.

Again: from the point of optimization 'public', 'private' attributes are
almost worthless.
But despite of that they are in the language. const is the same - it is a
contract.
Any argument that you can *intentionally* break constness are true.
The same apply to visibility attributes.

Andrew.