Цейлонская функция высшего порядка

У меня есть код:

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()();
}

Я не уверен, почему компилятор в порядке с объявлением «i2». Nothing является подтипом всего и, следовательно, подтипом пустого кортежа, поэтому я могу понять, почему я могу сделать объявление. Но как только я это сделал, мне кажется невозможным нормально вызывать «i2», поскольку вызов его без аргументов, пустой кортеж означает вызов его с супертипом того, что он хочет, который Цейлон отвергает. Так можно ли вообще вызвать getInt, возвращенный из i2?


person No Files    schedule 29.12.2016    source источник


Ответы (2)


Давайте немного изменим ваш пример.

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;
}

Как вы упомянули, Nothing является подтипом [], потому что это подтип всего. Это также подтип [Integer].

Тип Callable<Integer, Nothing> описывает любую функцию, которая возвращает Integer. Однако он не говорит, что не требует аргументов.

Можно вызвать функцию function, возвращенную из i2, но сначала вам нужно проверить ее тип:

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

Приведенный выше пример хорош, потому что [Integer, Integer] можно присвоить [Integer] и, следовательно, Callable<Integer, [Integer]> можно присвоить Callable<Integer, [Integer, Integer]>, поскольку параметр второго типа Callable является контравариантным.

person NiematojakTomasz    schedule 29.12.2016
comment
Привет, я не уверен, что ты имеешь в виду. Возможно, вы используете другой язык? val не является цейлонским, и [Integer, Integer] не может быть присвоено [Integer]. Ваш код компилируется, но оператор if не вводится. Ваша точка зрения кажется немного неуместной, я не уверен, что ваша точка зрения пытается быть. - person No Files; 29.12.2016

Callable<Integer, Nothing> является допустимым, потому что аргумент второго типа должен удовлетворять Anything[], что соответствует Nothing, потому что, как вы сказали, это подтип каждого типа. Но такая функция никогда не может быть вызвана, потому что она ожидает экземпляр Nothing, а такого экземпляра не существует.

Вы можете сделать apply(i2(), nothing), что порадует средство проверки типов, но, конечно, это просто сломается во время выполнения, потому что nothing — это заполнитель для чего-то, чего не может быть.

person gdejohn    schedule 29.12.2016
comment
Хорошо, это имеет смысл для меня. Я прочитал groups.google.com/forum/#!topic /ceylon-users/biVLQTmti-8, который помог мне понять больше, но я все еще немного сбит с толку, почему Цейлон позволяет мне стрелять себе в ногу, используя Nothing. - person No Files; 29.12.2016
comment
Компилятор предупреждает вас, если ваш код содержит выражения типа Nothing, и ваша программа немедленно взрывается, если во время выполнения встречается выражение типа Nothing. Ваши ноги в безопасности. - person gdejohn; 29.12.2016
comment
но я все еще немного сбит с толку, почему Ceylon позволяет мне выстрелить себе в ногу, используя Nothing - ну, вы действительно не должны использовать Callable напрямую, только когда вы точно знаете, что делаете. Альтернативный (намного более приятный) синтаксис без Callable (ваш i1()) совершенно безопасен. - person Quintesse; 29.12.2016