首页 > 解决方案 > 将列表附加到列表列表时,Rascal 会擦除类型信息

问题描述

我有以下功能:

public list[list[loc]] populateBeforeRemoval(){
    list[list[loc]] dupList = [];
    map[int, list[loc]] finalizedDups = ();

    // Here some stuff is added to the finalizedDups map, however, I have omitted it for simplicity.

    for(dup <- finalizedDups){
        dupList+=finalizedDups[dup];
    }
    return dupList;
}

但是,当我运行此函数时,我得到以下输出:

|project://TestProject/src/astCreation.rsc|(4955,3,<142,40>,<142,43>): Expected list[list[loc]], but got list[value]
Advice: |http://tutor.rascal-mpl.org/Errors/Static/UnexpectedType/UnexpectedType.html|

当我单击消息时,它指向dupList代码中的返回值 ( )。似乎添加finalizedDups[dup]删除了list[loc]列表的类型()。这应该不可能吧?

只是为了完整起见,这里是整个(实际)功能:

public list[list[loc]] populateBeforeRemoval(list[list[loc]] dupList, list[loc] potentialDuplicates, list[loc] newPotentialDuplicates, loc location, int lineNumber){
    map[int, list[loc]] finalizedDups = ();
    for(dup <- potentialDuplicates, getSourceLength(dup)>=6){
        bool sameIn = false;
        for(pot <- newPotentialDuplicates){
            if(pot.uri == dup.uri && pot.begin.line == dup.begin.line){
                sameIn = true;
            }
        }
        if(!sameIn){
            int srcLength = getSourceLength(dup);
            if(srcLength in finalizedDups){
                finalizedDups[srcLength]+=dup;
            } else {
                location.end.line = lineNumber-1;
                location.begin.line = lineNumber-srcLength-1;
                finalizedDups[srcLength]=[location, dup];
            }
        }
    }
    for(dup <- finalizedDups){
        dupList+=finalizedDups[dup];
    }
    return dupList;
}

更新:

一开始这段代码在eclipse IDE中显示了很多错误。重命名dup为其他内容后,大多数这些错误都消失了。这可能是因为是我导入的(http://tutor.rascal-mpl.org/Rascal/Libraries/Prelude/List/dup/dup.htmldup )中的一个函数。似乎是 Eclipse 插件的问题,显示为错误的行不会在运行时创建错误。List.rsc

然而,主要问题并没有解决。我认为这个问题是由于将列表附加到列表列表。

标签: rascal

解决方案


不错的代码。让我们来看看。仅从阅读未运行我怀疑将元素类型扩大到“值”的 += 运算符。

要知道的事情:

  • "+=" 对于列表上的连接和元素添加(仍然)重载
  • 如果这两种语义混合在一起,则分配的新元素类型是整个列表类型与其元素类型之间的最小上限,通常是“值”
  • 它有助于用列表括号包裹有问题的赋值的右侧,以强制“+=”的连接语义

不请自来的旁注:理解和关系运算符通常更快:

for(dup <- finalizedDups){
    dupList+=finalizedDups[dup];
}

可能是:dupList += [*finalizedDups[dup] | dup <- finalizedDups)];

+= 然后是单个连接,生成器像以前一样循环键,* 将映射中的每个列表值拼接到结果列表中。我没有测试这个只是大声思考。它更快,因为在引擎盖下 Rascal 可以使用瞬态可变状态直到列表理解完成,而 for 循环替代方案不假设任何内容并且仅使用不可变的内部 API。


推荐阅读