简体   繁体   English

Swift中使用泛型的递归枚举

[英]Recursive Enumerations with Generics in Swift

I'm new to Swift. 我是Swift的新手。 I was trying to implement a binary tree with recursive enumerations and generics: 我试图用递归枚举和泛型实现二叉树:

enum BinaryTree<T> {
  indirect case Node(T, BinaryTree<T>, BinaryTree<T>)
  case Nothing
}

func inorder<T>(_ root: BinaryTree<T>) -> [T] {
  switch root  {
  case .Nothing: 
    return []
  case let .Node(val, left, right):
    return inorder(left) + [val] + inorder(right) 
  }
}

Here's the error I got: 这是我得到的错误:

$ swift ADT.swift 
ADT.swift:83:20: error: cannot convert value of type 'BinaryTree<T>' to expected argument type 'BinaryTree<_>'
    return inorder(left) + [val] + inorder(right) 
                   ^~~~

However, this works: 但是,这有效:

func inorder<T>(_ root: BinaryTree<T>) -> [T] {
  switch root  {
  case .Nothing: 
    return []
  case let .Node(val, left, right):
    let l = inorder(left) 
    let r = inorder(right)
    return l + [val] + r
  }
}

Is there any mistakes in my syntax? 我的语法有错吗? Thanks! 谢谢!

I'm using Swift 3.0. 我正在使用Swift 3.0。

Update 更新
So I tried to condense the problem into minimal example code that fails to compile and asked a question myself and filed SR-4304 . 所以我试着将问题压缩成最小的示例代码,无法编译并自己提出问题并提交了SR-4304 Turns out the answer is that this really is a bug in the compiler. 原来答案是,这确实是编译器中的一个错误。

Original Answer 原始答案
As far as I can tell, your syntax is perfectly valid. 据我所知,你的语法是完全有效的。 It seems that the Swift compiler's type inference seems to need a nudge in the right direction which your second solution apparently provides. 似乎Swift编译器的类型推断似乎需要在第二个解决方案显然提供的正确方向上轻推。 As I experienced several similar problems in the past, especially regarding the + operator, your question inspired me to try several other ways to join the arrays. 由于我在过去经历过几个类似的问题,特别是关于+运算符,你的问题激发了我尝试其他几种加入数组的方法。 These all work (I am just showing the return statements and supporting functions for the last three cases): 这些都有效(我只是展示了最后三种情况的返回语句和支持函数):

return (inorder(left) as [T]) + [val] + inorder(right)
return Array([inorder(left), [val], inorder(right)].joined())
return [inorder(left), [val], inorder(right)].reduce([], +)
return [inorder(left), [val], inorder(right)].flatMap { $0 }

func myjoin1<T>(_ arrays: [T]...) -> [T]
{
    return arrays.reduce([], +)
}
return myjoin1(inorder(left), [val], inorder(right))

func myjoin2<T>(_ array1: [T], _ array2: [T], _ array3: [T]) -> [T]
{
    return array1 + array2 + array3
}
return myjoin2(inorder(left), [val], inorder(right))

extension Array
{
    func appending(_ array: [Element]) -> [Element]
    {
        return self + array
    }
}
return inorder(left).appending([val]).appending(inorder(right))

Calling the operator as a function compiles, too: 将操作符作为函数调用也会编译:

return (+)(inorder(left), [val]) + inorder(right)

It would be great if somebody with more intimate knowledge of the Swift compiler could shed some light on this. 如果对Swift编译器有更深入了解的人可以对此有所了解,那就太好了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM