在Rascal,说我有代码:
value x = 2;
data Exp = con(int n);
有没有办法调用con(x),而x是一个值(但实际上是一个整数),而不事先知道con的第一个参数的类型应该是什么(因此没有明确地将它转换为int )?
为什么可以调用一个函数,比如int something(int n)= n,将一个定义为值的整数(例如值y = 2)传递给它的第一个参数,而当我输入时它给出了一个错误尝试对用户定义的ADT做同样的事情吗?
答案 0 :(得分:0)
当你在Rascal中调用一个函数时,实际上它正在对参数进行模式匹配。因此,如果您定义int something(int n) = n;
,然后调用something(x)
,则会将x
与int n
匹配,看到x
实际上是int
(所以它可以将值绑定到n
),并调用该函数。
如果您要定义value x = 2.5
,然后调用something(x)
,则会收到错误,因为它无法将值2.5
绑定到int n
。您可以使用第二个定义来重载something
,而不是int something(real r) = toInt(r);
,然后它会起作用。但请注意两个问题:something
需要在两种情况下都返回相同的类型,并且您需要导入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
的话是int
你将得到一个你可以处理的错误,能够创建自己的错误消息,添加额外的错误处理而不仅仅是显示消息,查看导致问题的值等,而不仅仅是解释器给出错误(可能无法提供您想要的所有信息)。