Генератор последовательности как вызов функции расширения терпит неудачу с " несоответствием типа приемника"
Я играю с попыткой сгенерировать последовательность из одного значения Long
, предшествующего LongRange
. Это работает:
val seq = buildSequence<Long> {
yield(2)
yieldAll(3L..5)
}
Но пытаясь обобщить его, я не могу, кажется, структурировать функцию расширения, которую я могу успешно вызвать:
infix fun Long.join(R: LongRange): Sequence<Long> {
val start = this
return buildSequence<Long> {
yield(start)
yieldAll(R)
}
}
Когда я пытаюсь вызвать его:
(2 join 3..5).forEach { /* do something */ }
Я получаю
Ошибка: (26, 20) Котлин: неразрешенная ссылка. Ни один из следующих кандидатов не применим из-за несоответствия типа приемника: общественный инфикс весело Длинный.join (R: LongRange): последовательность, определенная в main.Котлин
Похоже, что компилятор распознает, что сигнатура функцииблизка к тому, что я пытаюсь достичь, но я явно не понимаю, что означает "несоответствие типа приемника".
1 ответ:
Ошибка "несоответствие типа приемника" означает, что то, чтопередается в качестве приемника функции расширения (т. е. то, что она вызывается), не соответствует объявленному типу приемника.
Котлин, в отличие от Явы, не продвигает числа к более широким числовым типам, и вы должны использовать
Long
литералы в коде, где ожидаетсяLong
:(2L join 3L..5).forEach { /* do something */ }
здесь использование
2
в качестве приемника не является вариантом, посколькуLong
ожидаемый. Но в3L..5
Использование5
нормально, потому что естьLong.rangeTo
перегрузка, которая принимаетInt
и возвращаетLongRange
.
Единственное исключение, когда существует автоматическое продвижение, - это когда вы присваиваетеInt
литерал переменной другого интегрального типа и передаетеInt
литерал в качестве аргумента функции, ожидающей другой интегральный тип (как было сказано выше, он не работает с приемниками).val a: Long = 5 // OK fun f(l: Long) { } f(5) // OK val b = 5 val c: Long = b // Error f(b) // Error