Implement a Kotlin Standard Library extension Function let
:
extension KtStd<T, R> on T {
R let(R f(T it)) => f(this);
}
And write a CLI sum calculator (The problem cannot be simplified), expect:
input: 1 2 3 4 5 6 7 8 9
output: 45
input: apple 1.2 banana 3.4
output: 4.6
Then code:
main() {
stdin.readLineSync(encoding: Encoding.getByName('utf-8')).split(" ")
.map((s) => double.tryParse(s)).where((e) => e != null).fold(0, (acc, i) => acc + i)
.let((d) => d % 1 == 0 ? d.toInt() : d)
.let((it) => print(it));
}
When input 1 2 3
, getting error message:
Unhandled exception:
NoSuchMethodError: Class 'double' has no instance method 'let'.
Receiver: 6.0
Tried calling: let(Closure: (dynamic) => dynamic)
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1 main (file:xxx.dart:xx:xx)
#2 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:301:19)
#3 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
In addition, if I change the fold
function into reduce
, giving the same input, getting error message:
Unhandled exception:
NoSuchMethodError: Class 'int' has no instance method 'let'.
Receiver: 6
Tried calling: let(Closure: (dynamic) => void)
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1 main (file:xxx.dart:xx:xx)
#2 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:301:19)
#3 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
The dart version is:
Dart VM version: 2.8.2 (stable) (Mon May 11 15:06:42 2020 +0200) on "windows_x64"
Why I got these error messages? How can I solve it?
Dart extensions are static. They are syntactic sugar that is applied on types that are known at compilation time. This means that extensions will not work on dynamic
values where the type is determined at runtime.
Your long, chained expression ends up using dynamic
types probably where you aren't expecting it. One problem is that when you do .fold(0, (acc, i) => acc + i)
, the parameter and return types of the callback are not deduced. (See https://github.com/dart-lang/language/issues/731.) acc
and the return type are thus assumed to be of type dynamic
.
You can fix that by explicitly specifying a type for fold
: .fold<double>(...)
.
In your edited version of your code, you introduced a second problem:
extension KtStd<T, R> on T {
R let(R f(T it)) => f(this);
}
You intend for KtStd<T, R>
to depend on let
to constrain R
, but that's backwards. let
is not a legal call without first making KtStd<T, R>
an extension on T
. R
therefore is unconstrained and is assumed to be dynamic
. That then forces let
to return dynamic
too.
If possible, I suggest reverting to your earlier version where let
is separately generic on R
:
extension KtStd<T> on T {
R let<R>(R f(T it)) => f(this);
}
You can more easily identify such errors during analysis by modifying your analysis_options.yaml
file and setting:
analyzer:
strong-mode:
implicit-casts: false
implicit-dynamic: false
language:
strict-raw-types: true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With