ADT 和值

ADTs and values

在 Rascal 中,假设我有代码:

value x = 2;
data Exp = con(int n);

有没有办法调用 con(x),而 x 是一个值(但实际上是一个整数),而无需事先知道 con 的第一个参数应该是什么类型(因此没有明确地将其转换为一个整数)?

为什么可以调用一个函数,比如 int something(int n) = n,将一个整数定义为一个值(例如值 y = 2)传递给它的第一个参数,同时它给我一个错误当我尝试对用户定义的 ADT 执行相同操作时?

当你在 Rascal 中调用函数时,它实际上是在对参数进行模式匹配。因此,如果您定义 int something(int n) = n;,然后调用 something(x),它会将 xint n 匹配,发现 x 实际上是一个 int(因此它可以将值绑定到 n),并调用该函数。

如果您改为定义 value x = 2.5 然后调用 something(x),您将收到错误消息,因为它无法将值 2.5 绑定到 int n。您可以使用取实数的第二个定义重载 something,例如 int something(real r) = toInt(r);,这样它就可以工作了。不过,这里需要注意两点:something 在两种情况下都需要 return 相同的类型,并且您需要导入 util::Math 才能访问 toInt.

当您使用构造函数时,例如 con(x),它不会自动为您进行模式匹配。您给它的类型必须与它期望的类型相匹配。如果您知道 x 将始终是 int,最好就这样声明它。另一种选择是创建一个像 Exp makeCon(int n) = con(n); 这样的函数,然后您可以随意使用它,即 Exp myExp = makeCon(x);。在这种情况下最好包含函数的默认版本,以防万一你给它一些意想不到的东西,比如 default Exp makeCon(value x) { throw "Unexpected value <x>"; },这样如果你试图用一些东西创建一个 con 't an int 你会得到一个你可以处理的错误,能够创建你自己的错误消息,添加额外的错误处理而不是仅仅显示一条消息,查看导致问题的值等等,而不是仅仅拥有口译员给出了一个错误(可能不会给你所有你想要的信息)。