Ceylon Higher Order Function

150 views Asked by At

I have the code:

shared Integer getInt() {
    return 42;
}

shared Integer() i1() {
    return getInt;
}

shared Callable<Integer,Nothing> i2() {
    return getInt;
}

shared Callable<Integer,[]> i3() {
    return getInt;
}

void run() {
    // OK
    i1()();
    // Illegal `[] is not assignable to Nothing`
    i2()();
    // OK
    i3()();
}

I am not sure why the compiler is OK with the "i2" declaration though. Nothing is a subtype of everything and therefore a subtype of the empty tuple, so I can kind of understand why I can do the declaration. But once I've done that it seems impossible for me to invoke "i2" normally as calling it with no arguments, empty tuple, means calling it with a supertype of what it wants which Ceylon rejects. So is it possible at all to invoke the getInt returned from i2?

2

There are 2 answers

1
NiematojakTomasz On

Lets modify your example a little bit.

shared Integer getInt(Integer x) {
    return 42 + x;
}

shared Integer(Integer) i1() {
    return getInt;
}

shared Callable<Integer,Nothing> i2() {
    return getInt;
}

shared Callable<Integer,[Integer]> i3() {
    return getInt;
}

As you mentioned Nothing is subtype of [], because it's subtype of everything. It is also subtype of [Integer].

Type Callable<Integer, Nothing> describes any function that returns Integer. However it doesn't say it takes no arguments.

It is possible to call function function returned from i2, but you need to typecheck it first:

val gi = i2();
if(is Callable<Integer, [Integer, Integer]> gi) {
     gi(1,2);
}

Above example is fine, because [Integer, Integer] is assignable to [Integer] and therefore Callable<Integer, [Integer]> is assignable to Callable<Integer, [Integer, Integer]>, as the second type parameter of Callable is contravariant.

3
gdejohn On

Callable<Integer, Nothing> is legal because the second type argument must satisfy Anything[], which Nothing does because, like you said, it's a subtype of every type. But such a function can never be invoked because it's expecting an instance of Nothing, and no such instance exists.

You can do apply(i2(), nothing), which makes the type checker happy, but of course that just blows up at run time because nothing is a placeholder for something that can't exist.