gpt4 book ai didi

arrays - flatMap 中的 "Cannot convert return expression"里面有一个无意义的表达式

转载 作者:行者123 更新时间:2023-11-30 11:50:22 25 4
gpt4 key购买 nike

我正在检查 .lazy 的高阶函数,并发现了一些与 flatMap 函数(可能还有其他函数)相关的有趣的编译错误

示例

 let array = [1, 2, 3, 4, 5, 6]array    .flatMap {        print("DD")        return $0 // Cannot convert return expression of type 'Int' to return type 'String?'    }    .forEach {        print("SS")        print($0)}

稍微注释一下

 array    .flatMap {//        print("DD")        return $0    }    .forEach {        print("SS")        print($0)}

一切正常......甚至更有趣的例子

 array    .flatMap {        let z = $0        return $0  // Or return z - all is the same "Cannot convert return expression of type 'Int' to return type 'String?'"    }    .forEach {        print("SS")        print($0)}

什么可能导致这种行为?

最佳答案

目前(从 Swift 4 开始)Sequence 上的 flatMap(_:) 方法有两种不同的含义:

  • 它可以采用返回可选 T? 的变换闭包,并且它将返回 [T],过滤掉 nil 结果(在未来版本中此重载 is to be renamedcompactMap(_:))。

    public func flatMap<ElementOfResult>(
    _ transform: (Element) throws -> ElementOfResult?
    ) rethrows -> [ElementOfResult]

  • 它可以采用返回序列的转换闭包,并且它将返回一个包含所有结果序列串联的数组。

    public func flatMap<SegmentOfResult : Sequence>(
    _ transform: (Element) throws -> SegmentOfResult
    ) rethrows -> [SegmentOfResult.Element]

现在,在 Swift 4 中,String 变成了 RangeReplaceableCollection(因此成为 Sequence)。 Swift 3 代码执行此操作:

// returns ["foo"], as using the `nil` filtering flatMap, the elements in the closure
// are implicitly promoted to optional strings.
["foo"].flatMap { $0 }

现在这样做:

// returns ["f", "o", "o"], a [Character], as using the Sequence concatenation flatMap,
// as String is now a Sequence (compiler favours this overload as it avoids the implicit
// conversion from String to String?)
["foo"].flatMap { $0 }

为了保持源兼容性,专门的 flatMap 重载 were added对于字符串:

//===----------------------------------------------------------------------===//
// The following overloads of flatMap are carefully crafted to allow the code
// like the following:
// ["hello"].flatMap { $0 }
// return an array of strings without any type context in Swift 3 mode, at the
// same time allowing the following code snippet to compile:
// [0, 1].flatMap { x in
// if String(x) == "foo" { return "bar" } else { return nil }
// }
// Note that the second overload is declared on a more specific protocol.
// See: test/stdlib/StringFlatMap.swift for tests.
extension Sequence {
@_inlineable // FIXME(sil-serialize-all)
@available(swift, obsoleted: 4)
public func flatMap(
_ transform: (Element) throws -> String
) rethrows -> [String] {
return try map(transform)
}
}

extension Collection {
@_inlineable // FIXME(sil-serialize-all)
public func flatMap(
_ transform: (Element) throws -> String?
) rethrows -> [String] {
return try _flatMap(transform)
}
}

这样,上述用法在 Swift 3 兼容模式中仍然会返回 [String],但在 Swift 4 中会返回 [Character]

那么,为什么

let array = [1, 2, 3, 4, 5, 6]

array
.flatMap {
print("DD")
return $0 // Cannot convert return expression of type 'Int' to return type 'String?'
}
.forEach {
print("SS")
print($0)
}

告诉你闭包应该返回一个String?

嗯,Swift 目前不会推断多语句闭包的参数和返回类型(有关更多信息,请参阅 this Q&A)。因此,flatMap(_:) 重载,其中闭包返回通用 T? 或通用 S : Sequence 不符合条件无需显式类型注释即可调用,因为它们需要类型推断来满足通用占位符。

因此,唯一符合条件的重载是特殊的 String 源兼容性重载,因此编译器期望闭包返回 String?

要解决此问题,您可以显式注释闭包的返回类型:

array
.flatMap { i -> Int? in
print("DD")
return i
}
.forEach {
print("SS")
print($0)
}

但是,如果您实际上并未在实际代码中使用此 flatMap(_:) 重载的可选过滤功能,则应该使用 map(_:)相反。

关于arrays - flatMap 中的 "Cannot convert return expression"里面有一个无意义的表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48383425/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com