Question

Why does the following work:

rascal>int increment(int x) = x + 1;
int (int): int increment(int);

rascal>int s = 5;
int: 5

rascal>increment(s);
int: 6

rascal>value vs = s;
value: 5

rascal>increment(vs);
int: 6

...while this fails:

rascal>data Side = leftSide() | rightSide();
ok

rascal>Side swap(leftSide()) = rightSide();
Side (Side): Side swap(Side);

rascal>Side swap(rightSide()) = leftSide();
Side (Side): Side swap(Side);

rascal>Side side = leftSide();
Side: leftSide()

rascal>swap(side)
Side: rightSide()

rascal>value vside = side;
value: leftSide()

rascal>swap(vside)
|stdin:///|(0,11,<1,0>,<1,11>): The called signature: swap(value),
does not match the declared signature:  Side swap(Side); (abstract pattern);  Side swap(Side); (abstract pattern);
Was it helpful?

Solution

Excellent question. In fact this is undefined behavior. When the type checker is finished both versions should give a static error, namely: "increment is not fully defined on value, only on int" and "swap is not fully defined on value, only on Side" or something in this vain.

To work around the static error, in the future, you would have to add alternatives like this to complete the functions on the requested types:

default int increment(value _) { 
  throw "??? how to increment something that is not an int???"; 
}

default Side swap(value x) { 
    throw "??? how to swap something that is not a Side???";
}

And then you would have dynamic/run-time errors again, but only if the parameter is dynamically not an int or a Side respectively ;-)

Note that the default is necessary otherwise the value parameter would overlap with the original definition which is statically not allowed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top