Design with appender: good or bad?

Chris wendlec at tcd.ie
Thu Apr 10 06:57:25 PDT 2014


On Thursday, 10 April 2014 at 13:53:46 UTC, Chris wrote:
> On Thursday, 10 April 2014 at 10:47:08 UTC, Rene Zwanenburg 
> wrote:
>> On Thursday, 10 April 2014 at 10:16:43 UTC, Chris wrote:
>>> Ah, this one \me (= escaped me). Sorry I wasn't precise, I 
>>> was wondering if it is in any way dangerous to have
>>>
>>> @property string[] items() {
>>> return buf.data;
>>> }
>>>
>>> instead of:
>>>
>>> string[] items;
>>> // ...
>>> public addItem(string item) {
>>> items ~= item;
>>> }
>>>
>>> because the two are not the same. When you print MyStruct to 
>>> console you get the address of appender buf, whereas when you 
>>> use string[] items you get the actual items. I'm only 
>>> wondereing if using appender is potentially dangerous and 
>>> could bite me later.
>>
>> The only thing I know of is if you store the reference 
>> returned by items(), clear the appender, and add new items, 
>> the contents of the previously returned slice will change too. 
>> Clearing an appender is similar to setting slice length to 0 
>> and calling assumeSafeAppend on it.
>
> Like so:
>
> import std.stdio, std.array;
>
> void main() {
>   auto mystr1 = MyStruct1("Hello1");
>   auto mystr2 = MyStruct2("Hello2");
>   mystr1.addItem("World1");
>   mystr2.addItem("World2");
>   auto data1 = mystr1.items;
>   writeln(mystr1.buf.data.length);
>   auto data2 = mystr2.items;
>   writeln(data1[0]);
>   writeln(data2[0]);
>   mystr1.clear();
>   mystr2.clear();
>   writeln(mystr1.buf.data.length);
>   writeln(data1[0]);
>   writeln(data2[0]);
>   mystr1.addItem("After World 1");
>   mystr2.addItem("After World 2");
>   writeln(mystr1.items[0]);
>   writeln(mystr2.items[0]);
>   writeln(data1[0]);  // Is now After World 1
>   writeln(data2[0]);  // Still is World2
> }
>
> struct MyStruct1 {
>   Appender!(string[]) buf;
>   string name;
>
>   this(string name) {
>     this.name = name;
>     buf = appender!(string[]);
>   }
>
>   public void addItem(string item) {
>     buf.put(item);
>   }
>
>   @property ref auto items() {
>     return buf.data;
>   }
>
>   public void clear() {
>     buf.clear();
>   }
> }
>
> struct MyStruct2 {
>   string[] stuff;
>   string name;
>
>   this(string name) {
>     this.name = name;
>   }
>
>   public void addItem(string item) {
>     stuff ~= item;
>   }
>
>   @property ref string[] items() {
>     return stuff;
>   }
>
>   public void clear() {
>     stuff.clear();
>   }
> }

The funny thing, though, is that after clearing buf

writeln(data1[0]);

still prints "World1". It only changes after I add a new item to 
buf.


More information about the Digitalmars-d-learn mailing list