swift - 具有通用参数或 T 或 T 数组的 Swift 重载函数中的意外行为

标签 swift generics higher-order-functions

我正在尝试通过泛型实现平面 map 。 (是的,平面 map 已经是该语言的一部分。)我尝试使用通用的重载函数来完成此任务。 (可能不是最有效的。我知道。我已经有了一个有效的命令式版本。)令我意想不到的是 flatten< T, U >( _ elem: T ) -> [ U ]即使重载 func flatten< T, U >( _ ary: [ T ] ) -> [ U ] 也正在消耗调用 flatten 的数组存在。

我知道出了什么问题,但我似乎不明白为什么,甚至不知道去哪里了解原因并可能修复它。

我什至尝试了几次转换,只是为了看看,这产生了错误,这对我来说是有意义的。为什么投 TT[ T ][ T ] ?。又改了aryelem看看这是否导致重载语义出现问题。产生相同的输出。

import Foundation

func flatten< T, U >( _ elem:    T   ) -> [ U ] {
    if let item = elem as? U {
        return [ item ]
    } else {
        return []
    }
}

func flatten< T, U >( _ ary:   [ T ] ) -> [ U ] {
    if ary.count == 0 {
        return []
    }

    return flatten( ary.first ) + flatten( Array( ary.dropFirst() ) )
}

let x: [ Int ] = flatten( [ 1, 2, [ 3, 4 ], [ [ 5, 6 ], nil, 7 ], 8, 9 ] )
print( x )  // Prints [1, 2, 8, 9 ] instead of [1, 2, 3, 4, 5, 6, 7, 8, 9]

最佳答案

编译器因使用来自 ary.first 的包装可选而感到困惑,它肯定会转到第一个函数签名。但即使解决了这个问题,在处理更简单的情况(例如 [[1,2][3,4]] 时仍然会留下一些歧义。

解决此问题的另一种方法是在内部处理所有类型,而不是将其留给编译器:

func flatten<U>( _ ary:[Any] ) -> [ U ]
{
    func makeFlat(_ flat:[U], _ elem:Any) -> [U]
    {
       if let item   = elem as? U     { return flat + [item] }
       if let ary    = elem as? [U]   { return flat + ary }
       if let subAry = elem as? [Any] { return flat + flatten(subAry) }
       return flat
    }
    return ary.reduce([U](),makeFlat)
}

关于swift - 具有通用参数或 T 或 T 数组的 Swift 重载函数中的意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46940722/

相关文章:

c# - 无法在列表 C# 中保存通用接口(interface)实现

java - java 可以从泛型之上定义的类推断出泛型类型吗?

reactjs - 如何在调用高阶组件时访问类外的 prop,以便高阶组件可重用

typescript - 在 Typescript 中注释高阶函数

powershell - 简洁地传递函数作为参数

ios - 在我的 ios swift TableView 中创建 2 个不同高度的动态单元格原型(prototype)

swift - 从图库上传图片

swift - 检测闭包内的对象(在 Linux Swift 中)

ios - 没有得到 iPhone 屏幕边界的正确高度

java - 在java中使用类型参数进行转换