Thread overview
D1 and read-only views?
Apr 10, 2009
Nick Sabalausky
Apr 11, 2009
Kagamin
Apr 12, 2009
Daniel Keep
April 10, 2009
Am I correct in my understanding of the following regarding D1?:

Suppose there's a D1 class like this:

class Foo
{
  // Johnny Coder wants the string to be readable from
  // outside Foo, but not changable from outside Foo.
  // He handles it as he would an int:

  private char[] _myStr;
  public char[] myStr()
  {
    return _myStr;
  }

  this()
  {
    // Have to awkwardly .dup this in case Foo
    // itself wants to modify _myStr in-place.
    _myStr = "bar".dup;
  }
}

That contains a bug (in "myStr()") because myStr() simply returns a pointer (and length, of course) to the actual data, and the caller could use that to change the data:

auto f = new Foo();
auto str = f.myStr();
assert(f.myStr() == "bar"); // Ok
str[0] = 'c';
assert(f.myStr() == "bar"); // FAIL!

Unlike C and D2, D1's const doesn't create a read-only view, but simply means the value is set at compile-time. D1 doesn't have anything else comparable to the C or D2 const so if Johnny Coder wants to make his interface to Foo safe, his only choice is to make myStr() duplicate the string:

  public char[] myStr()
  {
    return _myStr.dup;
  }

Is this all correct?

(Note, I'm not complaining about any of this, I realize it's all been improved in D2. Just making sure I understand the D1 version correctly.)


April 10, 2009
On Fri, Apr 10, 2009 at 1:21 PM, Nick Sabalausky <a@a.a> wrote:
> Am I correct in my understanding of the following regarding D1?:
>
> Suppose there's a D1 class like this:
>
> class Foo
> {
>  // Johnny Coder wants the string to be readable from
>  // outside Foo, but not changable from outside Foo.
>  // He handles it as he would an int:
>
>  private char[] _myStr;
>  public char[] myStr()
>  {
>    return _myStr;
>  }
>
>  this()
>  {
>    // Have to awkwardly .dup this in case Foo
>    // itself wants to modify _myStr in-place.
>    _myStr = "bar".dup;
>  }
> }
>
> That contains a bug (in "myStr()") because myStr() simply returns a pointer
> (and length, of course) to the actual data, and the caller could use that to
> change the data:
>
> auto f = new Foo();
> auto str = f.myStr();
> assert(f.myStr() == "bar"); // Ok
> str[0] = 'c';
> assert(f.myStr() == "bar"); // FAIL!
>
> Unlike C and D2, D1's const doesn't create a read-only view, but simply means the value is set at compile-time. D1 doesn't have anything else comparable to the C or D2 const so if Johnny Coder wants to make his interface to Foo safe, his only choice is to make myStr() duplicate the string:
>
>  public char[] myStr()
>  {
>    return _myStr.dup;
>  }
>
> Is this all correct?

Yes.
April 11, 2009
You can also create an indexer. As it's done in .net
April 12, 2009
As others have stated, your surmise is correct.

On a related note, I recently wrote a very simple cstring struct that acts like const(char)[] does in D2.  I was using unique interned strings, and didn't want any surprises.  You can still get a mutable reference to the string by using .toString, but the struct is really only there to prevent accidental modifications.

  -- Daniel