Язык D;структуры, неизменные данные и странные ошибки - PullRequest
1 голос
/ 26 мая 2011

Я изучаю язык D. Моя первая попытка - это простой 2D-вектор, который я могу добавить, вычесть, вычеркнуть и т. Д. У меня есть эта ошибка, когда я пытаюсь скомпилировать:

Ошибка:

Ошибка: (Vector2d __ctmp1245 = D4math2v28Vector2d6 _initZ; , __ctmp1245). это (this._x / l, this._y / l) не является изменяемым

Примечание: ошибка связана с Vector2d.dir ()

Код:

import std.math;
public struct Vector2d {

private const real _x;
private const real _y;

this(in real x, in real y) {
    _x = x; _y = y;
}

// Basic Properties ***************************************

@property const real X () { return _x; }

@property const real Y () { return _y; }

@property const real length () { return sqrt(_x*_x + _y*_y); }

// Operations ***************************************   

/**
* Define Equality 
*/
const bool opEquals(ref const Vector2d rhs) {
    return  approxEqual(_x, rhs._x) &&  approxEqual(_y, rhs._y);
}

/**
* Define unary operators + and - (+v)
*/
ref Vector2d opUnary(string op)() const
    if (op == "+" || op == "-")
{
    return Vector2d(mixin(op~"_x"), mixin(op~"_y"));
}

/**
* Define binary operator + and - (v1 + v2)
*/
ref Vector2d opBinary(string op) (ref const Vector2d rhs)
    if (op == "+" || op == "-")
{
    return Vector2d(mixin("_x" ~ op ~ "rhs._x"),mixin("_y" ~ op ~ "rhs._y"));
}

/**
* Scalar multiplication & division (v * 7)
*/
ref Vector2d opBinary(string op) (ref const real rhs) const
    if (op == "*" || op == "/")
{
    return Vector2d(mixin("_x" ~ op ~ "rhs"),mixin("_y" ~ op ~ "rhs"));
}

/**
* Dot Product (v1 * v2)
*/
ref real opBinary(string op) (ref const Vector2d rhs) const
    if (op == "*") {
        return _x*rhs._x + _y*rhs._y;
} 

/**
* Obtain the director vector of this vector.
*/
ref Vector2d dir() const {
    auto l = this.length();
    return Vector2d(_x / l, _y /l);
}

/**
* Obtains the projection of this vector over other vector
* Params:
*   b = Vector over project this vector
*/
ref Vector2d projectOnTo(in Vector2d b) const {
    return  b.dir() * (this * b.dir());
}

    }

Я не понимаю, почему у меня есть эта ошибка. Кроме того, я пытаюсь изменить классификатор типов безуспешно. Даже я получаю ту же ошибку, если я попробую это:

    ref Vector2d dir() const {
    auto l = this.length();
    return Vector2d(2,3);
 }

РЕДАКТИРОВАТЬ:

Я попытался удалить "const" из атрибутов и удалить "ref" из продукта Dot (я получаю совет, который не был lvalue). Ошибка теперь такая:

src / math / v2.d (82): Ошибка: this.opBinary (b.dir ()) не является lvalue

Строка 82:

return  b.dir() * (this * b.dir());

автоответ:

Я исправил последнюю ошибку, я изменил ProjectOnTo на это:

ref Vector2d projectOnTo(in Vector2d b) const {
    auto a = this * b.dir();
    return  b.dir() * a;
}

Плюс я запускаю модульное тестирование и вижу, что Vector2d все в порядке.

Итак, теперь я наконец знаю, что не могу использовать неизменяемые переменные для атрибутов структуры, но я не понимаю, почему.

Ответы [ 2 ]

2 голосов
/ 26 мая 2011

исключите const квалификаторы полей

public struct Vector2d {

    private real _x;
    private real _y;

    this(in real x, in real y) {
        _x = x; _y = y;
    }
    //...

const не требуется, и это заблокирует вас от простого назначения:

Vector2d v;
v = Vector2d(0,0);

это не будет компилироваться

и помните, что универсальные функции (opBinary и opUnary) проверяются на синтаксис только тогда, когда они анализируются не на правильность кода (ваш opUnary возвращает Vector!T, но T универсальный тип никогда не объявляется (и, следовательно, не определен), но он проходит компиляцию ...)


edit Я создал свою собственную структуру с перегрузками операторов и за исключением opCmp и opEqualsЯ не использую ref const для параметров, просто const (in также хорошо подходит для этого)

edit2 Я нашел, что проще всего понимать структуры как группыпеременные, которые могут быть объявлены, назначены и использованы одновременно с несколькими дополнительными функциями, определенными для группы переменных

, поэтому Vector2D v; в вашем исходном коде будет затем переведено как const real v__x; const real v__y; присваивание v = Vector(0,0); тогда будет (после включенияконструктор), переведенный как v__x = 0;v__y = 0;

, но, поскольку v__x объявлен как const, это не будет разрешено

0 голосов
/ 26 мая 2011

Я пытался переписать тело dir() как

Vector2d v = Vector2d(0, 0);
return v;

и увидел хорошее сообщение об ошибке:

vector2D.d (67): ошибка: переменная vector2D.Vector2d.dir.v не может изменить структуру с неизменными членами
vector2D.d (67): Ошибка: экранирование ссылки на локальную переменную v

Я не понимаю, как переменнаямог изменить структуру, но это подсказало мне: почему вы определили _x и _y как const ?Я удалил const из их объявлений, и он скомпилировал:)

...