语言D;结构,不可变数据和奇怪的错误

时间:2011-05-26 09:04:19

标签: immutability d

我正在学习语言D.我的第一次尝试是一个简单的2d Vector,我可以添加,减去,点积等... 我尝试编译时遇到此错误:

错误:

  

错误:(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”并从Dot产品中删除“ref”(我得到的建议不是lvalue)。现在错误是这样的:

  

src / math / v2.d(82):错误:this.opBinary(b.dir())不是左值

第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它正常。

所以,最后我现在知道我不能将不可变变量用于struct属性,但我不明白为什么。

2 个答案:

答案 0 :(得分:2)

删除字段的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);

这不会编译

并且请记住,泛型函数(opBinaryopUnary)仅在解析它们的语法时进行测试而不是代码的正确性(您的opUnary返回{{1但Vector!T泛型类型从未声明(因而未定义)但这通过了编译......)


编辑我已经使用运算符重载创建了自己的结构,除了TopCmp我不会仅使用opEquals作为参数ref const({{1对于这个也很有效)

edit2 我发现最简单的方法是将结构理解为可以同时声明,分配和使用的变量组,并在一组变量周围定义一些额外的函数

因此原始代码中的const将被翻译为in,然后将Vector2D v;赋值(在内联构造函数后)翻译为const real v__x; const real v__y;

但由于v__x被声明为v = Vector(0,0);,因此不允许

答案 1 :(得分:0)

我试图将dir()的正文重写为

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

然后看到一条很好的错误消息:

  

vector2D.d(67):错误:变量vector2D.Vector2d.dir.v无法使用不可变成员修改struct   vector2D.d(67):错误:转义对局部变量v

的引用

我不明白变量如何修改结构,但这给了我一个提示:为什么你将_x和_y定义为 const ?我从声明中删除了 const ,并编译了:)