【问题标题】:Language D ; structs, immutable data and weird error语言 D ;结构、不可变数据和奇怪的错误
【发布时间】:2011-05-26 09:04:18
【问题描述】:

我正在学习语言 D。我的第一次尝试是一个简单的 2d 矢量,我可以添加、减去、点积等... 当我尝试编译时出现此错误:

错误:

错误:(Vector2d __ctmp1245 = D4math2v28Vector2d6_initZ; , __ctmp1245).this(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”(我得到的建议不是左值)。现在的错误是这样的:

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 运行良好。

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

【问题讨论】:

  • 您可以尝试在返回类型中删除ref 吗?
  • 顺便问一下,您使用哪个编译器?
  • @xs0,删除 ref 确实有帮助,但是......它看起来像一个编译器错误,在 ref 之前几行并且没有投诉...
  • 那是因为编译器只对模板进行语法控制(包括运算符重载函数),如果你添加一个unittest{Vector2d v;v+v;},它会抱怨它然后
  • @xs0 从 dir() 中删除“ref”和“const”不会改变任何东西,同样的错误。

标签: immutability d


【解决方案1】:

删除字段的 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 返回 Vector!TT 泛型类型从未被声明(因此未定义)但它通过了编译...)


编辑我已经用运算符重载创建了自己的结构,除了opCmpopEquals 我不使用ref const 作为参数只是constin 也适用于此)

edit2我发现将结构体理解为一组变量最容易理解,这些变量组可以同时声明、分配和使用,并在变量组周围定义一些额外的函数

因此,您原始代码中的Vector2D v; 将被翻译为const real v__x; const real v__y;,然后分配v = Vector(0,0); 将(在内联构造函数后)被翻译为v__x = 0;v__y = 0;

但由于 v__x 被声明为 const,这是不允许的

【讨论】:

  • 糟糕! Vector!T 来自我制作的以前版本,它更通用,适用于 N 维向量。我放弃了这些通用的,因为我对这些错误感到厌烦。谢谢
  • @zardoz 检查我的编辑以获取有关失败原因的更多信息
【解决方案2】:

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

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

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

vector2D.d(67):错误:变量 vector2D.Vector2d.dir.v 无法修改具有不可变成员的结构
vector2D.d(67):错误:转义对局部变量 v 的引用

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-13
    • 1970-01-01
    • 1970-01-01
    • 2016-06-07
    • 1970-01-01
    相关资源
    最近更新 更多