实现 Kotlin 标准库扩展函数let:
extension KtStd<T, R> on T {
R let(R f(T it)) => f(this);
}
Run Code Online (Sandbox Code Playgroud)
并编写一个 CLI sum 计算器(问题不能简化),期望:
input: 1 2 3 4 5 6 7 8 9
output: 45
input: apple 1.2 banana 3.4
output: 4.6
Run Code Online (Sandbox Code Playgroud)
然后代码:
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));
}
Run Code Online (Sandbox Code Playgroud)
输入时1 2 3,得到错误信息:
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)
Run Code Online (Sandbox Code Playgroud)
此外,如果我将fold函数更改为reduce,给出相同的输入,则会收到错误消息:
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)
Run Code Online (Sandbox Code Playgroud)
飞镖版本是:
Dart VM version: 2.8.2 (stable) (Mon May 11 15:06:42 2020 +0200) on "windows_x64"
Run Code Online (Sandbox Code Playgroud)
为什么我收到这些错误消息?我该如何解决?
Dart 扩展是静态的。它们是应用于编译时已知类型的语法糖。这意味着扩展不适用于dynamic在运行时确定类型的值。
您的长链表达式最终会使用dynamic您可能不期望的类型。一个问题是,当您这样做时.fold(0, (acc, i) => acc + i),不会推导回调的参数和返回类型。(请参阅https://github.com/dart-lang/language/issues/731。)acc并且返回类型因此被假定为 类型dynamic。
fold您可以通过显式指定:的类型来解决此问题.fold<double>(...)。
在您编辑的代码版本中,您引入了第二个问题:
extension KtStd<T, R> on T {
R let(R f(T it)) => f(this);
}
Run Code Online (Sandbox Code Playgroud)
您打算KtStd<T, R>依赖于letconstrain R,但这是倒退的。如果没有首先在 上进行延期,let则不是合法的呼叫。因此 是不受约束的并且被假定为。这也迫使我们返回。KtStd<T, R>TRdynamicletdynamic
如果可能,我建议恢复到早期版本,其中let单独通用R:
extension KtStd<T> on T {
R let<R>(R f(T it)) => f(this);
}
Run Code Online (Sandbox Code Playgroud)
analysis_options.yaml通过修改文件和设置,您可以在分析过程中更轻松地识别此类错误:
analyzer:
strong-mode:
implicit-casts: false
implicit-dynamic: false
language:
strict-raw-types: true
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1150 次 |
| 最近记录: |