我发现有时我必须为模式变量明确指定类型,否则 Rascal 将无法按预期工作。控制台中的以下会话说明了一切:
rascal>data foo = bar(int);
ok
rascal>int x = 1;
int: 1
rascal>[x | bar(x) <- [bar(2), bar(3)]];
list[void]: []
rascal>[x | bar(int x) <- [bar(2), bar(3)]];
list[int]: [2,3]
为什么会这样?
我发现有时我必须为模式变量明确指定类型,否则 Rascal 将无法按预期工作。控制台中的以下会话说明了一切:
rascal>data foo = bar(int);
ok
rascal>int x = 1;
int: 1
rascal>[x | bar(x) <- [bar(2), bar(3)]];
list[void]: []
rascal>[x | bar(int x) <- [bar(2), bar(3)]];
list[int]: [2,3]
为什么会这样?
在当前版本的 Rascal 中,存在于周围范围内的模式中的变量不会匹配和隐藏,而是检查是否相等。
所以:
<int x, x> := <2,2> => true // x is first introduced and then checked for equality
<int x, x> := <2,3> => false // x is first introduced and then checked for equality
{ int x = 1; if (x := 2) println("true"); else println("false"); // false!
这适用于我们使用模式匹配的所有地方。
我们已经对这种“非线性匹配”的特殊设计提出了一些抱怨,我们打算很快添加一个运算符 ($) 来识别从环绕范围中获取某些东西的意图。如果不使用操作符,则会出现阴影:
<int x, $x> := <2,2> => true // x is first introduced and then checked for equality
<int x, $x> := <2,3> => false // x is first introduced and then checked for equality
<int x, x> := <2,3> // static error due to illegal shadowing
<int x, y> := <2,3> => true // x and y are both introduced
{ int x = 1; if ($x := 2) println("true"); else println("false"); // false!
{ int x = 1; if (x := 2) println("true <x>"); else println("false"); // true, prints 2! or perhaps a static error.
还可以添加一些额外的功能来将表达式转换为模式,如下所示:
<1, ${1 + 2 + 3}> := <1,6> // true