rascal

Why does lacking explicit type declaration in parameter work when function is used directly, but not when it is passed to another function?


Have this function defined in your module:

module Data

int inc(x) = x + 1;

Type this in the console:

rascal> import Data;
rascal> import List;

This works:

rascal> inc(1);
int: 2

But this does not:

rascal> list[int] y = [1,2,3];
rascal> mapper(y, inc); 
|rascal://<path>|: insert into collection not supported on value and int
☞ Advice

But it works if inc(...)'s parameter type is declared:

int inc(int x) = x + 1;

So why does not having this type declaration work for using the inc(...) function directly, but not for passing that function to mapper(...)?


Solution

  • Because Rascal's type checker is still under development, you are not warned if you make a small mistake like forgetting to provide a type for a function parameter. It may still work, accidentally, in some circumstances but you are guaranteed to run into trouble somewhere as you've observed. The reason is that type inference for function parameters is simply not implemented as a feature. This is a language design decision with the intent of keeping error messages understandable.

    So, this is not allowed:

    int f(a) = a + 1;
    

    And, it should be written like this:

    int f(int a) = a + 1;
    

    I consider it a bug that the interpreter doesn't complain about an untyped parameter. It is caused by the fact that we reuse the pattern matching code for both function parameters and inline patterns. [edit: issue has been registered here]

    In your case the example works because dynamically the type of the value is int and addition does not check the parameter types. The broken example breaks because the interpreter does checks the type of the function parameter at the call-site (which defaulted to value for the untyped parameter).