March 19, 2007
Daniel Keep wrote:
> 
> Andrei Alexandrescu (See Website For Email) wrote:
>> (Reposted after cleanup :o))
>>
>> kris wrote:
>>> How about some further example? Given these sigs:
>>>
>>> struct Foo
>>> {
>>>    int a;
>>> }
>>>
>>> class Bar
>>> {
>>>    char[] b;
>>> }
>>>
>>> void fooish (inout Foo foo) {}
>>>
>>> char[] barish (Bar bar) {return bar.b;}
>>>
>>>
>>> 1) how do I modify the function decls to have the compiler *enforce*
>>> readonly upon the referenced content? e.g. Foo.a and Bar.b cannot be
>>> mutated within the function body?
>> void fooish (const ref Foo foo) {}
>>
>> char[] barish (const Bar bar) {return bar.b;}
>>
>>> 2) how does the fooish() decl change to have the compiler *enforce* a
>>> readonly-view of the returned bar.b?
>> const char[] barish (const Bar bar) {return bar.b;}
> 
> Hang on... wouldn't that need to be the signature of barish in the first
> place?  If const is transitive, bar is declared as a const Bar and
> you're returning bar.b, isn't bar.b const as well?

"Nobody said all examples must compile" -- Andrei

:o)

Andrei
March 19, 2007
Derek Parnell wrote:
> On Mon, 19 Mar 2007 15:05:29 -0700, Andrei Alexandrescu (See Website For
> Email) wrote:
> 
> 
> I wish it wasn't so hard to get a simple straight answer from the experts.

I think discussion would much improved if big changes like this actually came with a detailed proposal on a website somewhere that people could refer to and which would actually be updated to reflect vague points clarified during discussion.  As it is, there are a lot of points that have been clarified, and questions answered, but they're strewn across 100 different posts.  I'm pretty lost.  I gave up trying to follow this myself.  I'm hoping you'll figure it out and post something coherent. :-)

On the bright side, thanks to Andrei, at least there *is* an open discussion going on about the feature before it just shows up in the change log as a done deal.

--bb
March 19, 2007
Sean Kelly wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>>
>> By the way, a couple of days ago I've had an idea. Many people here ask
>> for a "string" alias because char[] is a tad hard to type and uneasy on
>> the eyes. Probably a good candidate would be:
>>
>> alias invariant char[] string;
>>
>> The resulting type is pretty damn slick:
> ...
>> 3. The ~= operator works (somewhat surprisingly).
> 
> I assume this is because a char[] is actually a struct containing a pointer, so 'invariant' allows that pointer to be reassigned--it simply protects the referenced string?  This is the sticking point for me. 

That is correct. For an understanding of a ~= b, think of it as a = a ~ b. Do I modify the stuff indirectly referenced by "a"? No, Sir. I just rebind a to a larger entity that embeds a copy of its former self.

In practice, the concatenation will not always produce a copy. The implementation will work "as if" you always produce a copy.

> Assume we have this:
> 
>     struct Foo
>     {
>         int  x;
>         int* y;
>     }
> 
>     const Foo foo; // is this legal?

Yes.

>     foo.x  = 1;    // this is allowed

Yes.

>     *foo.y = 2;    // this is not allowed

It's not allowed.

> Is that correct, or do 'const' and 'invariant' truly only apply to pure reference types?

No. They apply to any type that embeds references.

"final" applies to all types and guards the bits of the symbol itself. "final const" guards symbol bits + referenced bits, and "final invariant" is as opposed to change as the 19th century British education system. (Did I get that right?)

>> 4. It's very, very rare that you want to modify some random character in
>> a string, and when you do, use a char[] and then copy it back into a
>> string, or rebuild the string from slices!
> 
> This may be true for a string, but for arrays in general I think this is fairly common.

Yes. That's why arrays will stay in place :o).


Andrei
March 19, 2007
jovo wrote:
> Andrei Alexandrescu (See Website For Email) Wrote:
>> Yes. D's const is transitive.
>>
> 
> So:
> finall = stage0_nontransitive_const?
> const = stage1_transitive_const?

If I understand the above properly, yes.

> May be beter to separete concepts?
> 
> Do we need stage1_const?
> Do we need nontransitive_const?

So rarely that we decided they can be ruled out. They'd complicate the type system gravely, for very little benefit.

Andrei
March 19, 2007
Bill Baxter wrote:
> Derek Parnell wrote:
>> On Mon, 19 Mar 2007 15:05:29 -0700, Andrei Alexandrescu (See Website For
>> Email) wrote:
>>
>>
>> I wish it wasn't so hard to get a simple straight answer from the experts.
> 
> I think discussion would much improved if big changes like this actually came with a detailed proposal on a website somewhere that people could refer to and which would actually be updated to reflect vague points clarified during discussion.  As it is, there are a lot of points that have been clarified, and questions answered, but they're strewn across 100 different posts.  I'm pretty lost.  I gave up trying to follow this myself.  I'm hoping you'll figure it out and post something coherent. :-)
> 
> On the bright side, thanks to Andrei, at least there *is* an open discussion going on about the feature before it just shows up in the change log as a done deal.

I agree. (How couldn't I? Flattery goes a long way :o).)

Maybe we could imitate what other languages do, e.g. Perl has the famous "apocalypses" that describe each language feature in detail.


Andrei
March 19, 2007
On Tue, 20 Mar 2007 08:29:31 +0900, Bill Baxter wrote:

> On the bright side, thanks to Andrei, at least there *is* an open discussion going on about the feature before it just shows up in the change log as a done deal.

Amen to that.

A *HUGE* thank you to Andrei for being so available and willing to suffer fools gladly. This discussions extremely important for everybody an the big W just can't do it all.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Justice for David Hicks!"
20/03/2007 10:49:22 AM
March 20, 2007
Derek Parnell wrote:
> On Tue, 20 Mar 2007 08:29:31 +0900, Bill Baxter wrote:
> 
>> On the bright side, thanks to Andrei, at least there *is* an open discussion going on about the feature before it just shows up in the change log as a done deal.
> 
> Amen to that. 
> 
> A *HUGE* thank you to Andrei for being so available and willing to suffer
> fools gladly. This discussions extremely important for everybody an the big
> W just can't do it all. 

I thank you folks. Sharing is great. Studying alone is learning from a fool.

Andrei
March 20, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> Bill Baxter wrote:
>> Derek Parnell wrote:
>>> On Mon, 19 Mar 2007 15:05:29 -0700, Andrei Alexandrescu (See Website For
>>> Email) wrote:
>>>
>>>
>>> I wish it wasn't so hard to get a simple straight answer from the experts.
>>
>> I think discussion would much improved if big changes like this actually came with a detailed proposal on a website somewhere that people could refer to and which would actually be updated to reflect vague points clarified during discussion.  As it is, there are a lot of points that have been clarified, and questions answered, but they're strewn across 100 different posts.  I'm pretty lost.  I gave up trying to follow this myself.  I'm hoping you'll figure it out and post something coherent. :-)
>>
>> On the bright side, thanks to Andrei, at least there *is* an open discussion going on about the feature before it just shows up in the change log as a done deal.
> 
> I agree. (How couldn't I? Flattery goes a long way :o).)
> 
> Maybe we could imitate what other languages do, e.g. Perl has the famous "apocalypses" that describe each language feature in detail.

I was thinking more of Python's PEPs, but yeh, same deal.  I like PEPs in that anyone can submit one, get it assigned an offical number.   As opposed to Larry's stone tablets brought down from the mountain top for the rest of us to ooh and ahh over.  Python's way is a little more egalitarian.

Semi-official Enhancement Proposals are also a good way to handle the many repeated requests for 'feature X'.   Just tell 'em -- great idea, now go write a DEP for it.  If they actually do it, then great.  Next time someone asks for the feature you just point 'em to the previous DEP and the BFD ruling on it.

My impression is that PEPs get weighted somehow based on how fleshed-out they are.  For instance it seems a majority of PEPs (at least the ones I've read) come complete with prototype implementations.  So PEP is more than just a vague wish like "Please implement Java-style serialization".  It has to contain the nitty gritty details.

--bb
March 20, 2007
On Mon, 19 Mar 2007 16:20:04 -0700, Andrei Alexandrescu (See Website For
Email) wrote:

> Derek Parnell wrote:
>> I wish it wasn't so hard to get a simple straight answer from the experts.
> 
> It's not like anybody tries to obfuscate their writing.

LOL ... I realize that. Some people are just naturals at it.

>> So far I think /The W&A Show/ is saying that 'const' and 'invariant' only apply to reference data types (objects, variable-length arrays, and pointers) and structs. They do not apply *in any way, shape or form* to any other data type.
>> 
>>   const char[] s;    // ok
>>   const char   c;    // meaningless, the 'const' is ignored.
>>   const classFoo f;  // okay
>>   const double* b;   // okay;
>>   const double  d;   // meaningless, the 'const' is ignored.
>>   const structBar q; // okay
>> 
>> 'const' means you cannot change the stuff the reference is referencing or the members of the struct, *but* for reference types you can change the reference value.
>> 
>>   s[0] = 'a'; // fails
>>   s    = "new data"; //ok
>>   s.length = 2; // ok
>> 
>>   c    = 'a'; // ok
>> 
>>   f.bar = 'a'; // fails
>>   f = new classFoo(); // okay
>> 
>>   *b    = 1.0; // fails
>>   b     = &someDouble; // ok
>> 
>>   d     = 1.0; // okay
>> 
>>   q.foo = 'a'; // fails
> 
> Correct.


YAY!!!! Finally something has sunk in to my head <G>

>> 'invariant' means you cannot change the stuff the reference is referencing or the members of the struct, *and* for reference types you cannot change the reference value.
> 
> No. Invariant means that the data referenced indirectly is never modifiable by any part of the program.
> 
> What you called 'invariant' above is 'final const'.

Hmmm ... so the difference between 'const' and 'invariant' is that const is only effective for one level deep, but 'invariant' is effective for all levels, right?

  struct Foo
  {
      int a;
      int* b;
      Foo c;
      Foo* d;
  }

  const Foo f_const;
  invariant Foo f_invar;
  int x;

  // assuming we can initialize f_const and f_invar at run time somehow,
  // then are the following subsequent assignments as stated?
  f_const.a = 1;       // fails
  f_const.b = &x;      // fails
  *f_const.b = 1;      // okay;
  f_const.c.a = 1;     // okay
  f_const.c.b = &x;    // okay
  *f_const.c.b = 1;    // okay
  f_const.d = new Foo; // fails
  f_const.d.a = 1;     // okay
  f_const.d.b = &x;    // okay
  *f_const.d.b = 1;    // okay

  f_invar.a = 1;       // fails
  f_invar.b = &x;      // fails
  *f_invar.b = 1;      // fails;
  f_invar.c.a = 1;     // fails
  f_invar.c.b = &x;    // fails
  *f_invar.c.b = 1;    // fails
  f_invar.d = new Foo; // fails
  f_invar.d.a = 1;     // fails
  f_invar.d.b = &x;    // fails
  *f_invar.d.b = 1;    // fails


> [snip]
>> However, if this is the interpretation of 'invariant', how does one ever get to set the 'invariant' thing's value?
>> 
>>    invariant byte[] vCodes;
>>    . . .
>>    vCodes = LoadCodesFromFile();  // fails, no???
> 
> Right now you can only initialize invariant with literals. This aspect of the language is still under development. (Things like the result of some_string.dup also come to mind.)

Oh ... okay. I'll wait for that mind bender then.

>>  void func( string s )
>>  {
>>      char[] u;
>>      u = s;
> 
> You can't make the assignment u = s.

Oh, okay. The compiler will stop at "u = s;" because that would have made
access to 's' data via the 'u' symbol. Got it.

>>> 3. The ~= operator works (somewhat surprisingly).
>>  void func( string s )
>>  {
>>      string t;
>>      char[] u;
>> 
>>      u ~= s; // ok
>>      s ~= 'a'; // fails ???
>> 
>>      t ~= s; // fails???
>>  }
> 
> s ~= a; works and is equivalent to s = s ~ a, i.e. "rebind s to the concatenation of s and a". It's an operation that does not mutate s's contents.

So, could this be the mechanism to set an invariant array?

   invariant ubyte[] b;
   b ~= Load_Stuff_From_File();

>>> 4. It's very, very rare that you want to modify some random character in a string, and when you do, use a char[] and then copy it back into a string, or rebuild the string from slices!
>> 
>> It is not so rare in the type of applications that I do.
> 
> You use char[] for that, and when you are done modifying, you can put things in a string.

Oops. I was using "string" in the normal sense and not your new alias idea. In the context of the alias 'string' then what you say makes a lot of sense.

> It's like watching TV: you can always change your choice of watching

(Not if my wife has the remote <G>)

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Justice for David Hicks!"
20/03/2007 10:53:00 AM
March 20, 2007
Bill Baxter wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
> 
>> Bill Baxter wrote:
>>
>>> Derek Parnell wrote:
>>>
>>>> On Mon, 19 Mar 2007 15:05:29 -0700, Andrei Alexandrescu (See Website For
>>>> Email) wrote:
>>>>
>>>>
>>>> I wish it wasn't so hard to get a simple straight answer from the experts.
>>>
>>>
>>> I think discussion would much improved if big changes like this actually came with a detailed proposal on a website somewhere that people could refer to and which would actually be updated to reflect vague points clarified during discussion.  As it is, there are a lot of points that have been clarified, and questions answered, but they're strewn across 100 different posts.  I'm pretty lost.  I gave up trying to follow this myself.  I'm hoping you'll figure it out and post something coherent. :-)
>>>
>>> On the bright side, thanks to Andrei, at least there *is* an open discussion going on about the feature before it just shows up in the change log as a done deal.
>>
>>
>> I agree. (How couldn't I? Flattery goes a long way :o).)
>>
>> Maybe we could imitate what other languages do, e.g. Perl has the famous "apocalypses" that describe each language feature in detail.
> 
> 
> I was thinking more of Python's PEPs, but yeh, same deal.  I like PEPs in that anyone can submit one, get it assigned an offical number.   As opposed to Larry's stone tablets brought down from the mountain top for the rest of us to ooh and ahh over.  Python's way is a little more egalitarian.
> 
> Semi-official Enhancement Proposals are also a good way to handle the many repeated requests for 'feature X'.   Just tell 'em -- great idea, now go write a DEP for it.  If they actually do it, then great.  Next time someone asks for the feature you just point 'em to the previous DEP and the BFD ruling on it.
> 
> My impression is that PEPs get weighted somehow based on how fleshed-out they are.  For instance it seems a majority of PEPs (at least the ones I've read) come complete with prototype implementations.  So PEP is more than just a vague wish like "Please implement Java-style serialization".  It has to contain the nitty gritty details.
> 
> --bb

The PEP numbers are also a convenient way to refer to certain issues or features: "Oh the 'with' statement? That's PEP 343." The PEP can also serve as a starting point for the official documentation of the feature.

Most importantly, they serve as a fixed locus of discussion, and can vastly improve the low signal-to-noise ratio that running around in circles on a mailing list or newsgroup can cause.

In other words:
DEPs++

-- 
Kirk McDonald
http://kirkmcdonald.blogspot.com
Pyd: Connecting D and Python
http://pyd.dsource.org