Другие уже указывали, что addMsg не является чистым и не может быть чистым, поскольку он изменяет состояние объекта.
Единственный способ сделать его чистым - это инкапсулировать изменения, которые вы делаете. Самый простой способ сделать это с помощью обратной мутации, и для этого есть два способа.
Во-первых, вы можете сделать это так:
class TestPure
{
string[] msg;
pure TestPure addMsg(string s)
{
auto r = new TestPure;
r.msg = this.msg.dup;
r.msg ~= s;
return r;
}
}
Вам необходимо скопировать предыдущий массив, потому что внутри чистой функции ссылка this на самом деле является константой. Обратите внимание, что вы могли бы сделать копию лучше, выделив новый массив конечного размера, а затем скопировав элементы в себя. Вы бы использовали эту функцию так:
pure TestPure run3()
{
auto t = new TestPure;
t = t.addMsg("Test");
t = t.addMsg("this.");
return t;
}
Таким образом, мутация ограничивается каждой чистой функцией с изменениями, передаваемыми через возвращаемые значения.
Альтернативный способ написания TestPure состоял бы в том, чтобы сделать члены const и сделать всю мутацию перед передачей ее конструктору:
class TestPure
{
const(string[]) msg;
this()
{
msg = null;
}
this(const(string[]) msg)
{
this.msg = msg;
}
pure TestPure addMsg(string s)
{
return new TestPure(this.msg ~ s);
}
}
Надеюсь, это поможет.