我想使用一个函数来扩展Array,该函数将返回Array中所有非零项的计数。理想情况下,这可以使用任何可选或非可选类型的数组。我尝试了无法编译,崩溃的Xcode或两者的各种事情。我会假设它会像这样:
extension Array { func realCount() -> Int { var cnt = 0 for value in self { if value != nil { cnt++ } } return cnt } }
这里Swift抱怨说T不能转换为UInt8。或有时MirrorDisposition或其他随机类。
所以假设有可能,有什么诀窍?
编辑:从Xcode 6 beta 5开始,现在编译,但没有给出预期的结果。如果value!= nil每次都评估为true。
你不能将任意值与nil进行比较(编辑:但请参阅下面的Sulthan的评论;可能是我们应该能够将任意值与nil进行比较;这段落的其余部分今天可能是正确的,但只是由于编译器BUG)。虽然Optional可以使用一些句法糖来应用它,但它只是一个枚举,而nil只是Optional.None。您需要一种类型(可选)的行为和所有其他类型的其他行为。 Swift通过泛型,只是不在扩展。你必须把它变成一个功能:
func realCount<T>(x: [T?]) -> Int { return countElements(filter(x,{ $0.getLogicValue() } ) ) } func realCount<T>(x: [T]) -> Int { return countElements(x) } let l = [1,2,3] let lop:[Int?] = [1,nil,2] let countL = realCount(l) // 3 let countLop = realCount(lop) // 2
这种方法更加灵活。可选只是你想要flatMap的许多类型之一(例如,您可以使用相同的技术来处理Result)。
编辑:您可以通过为您认为“真实”的事物创建协议来进一步。这样你就不必把它限制在可选项。例如:
protocol Realizable { func isReal() -> Bool } extension Optional: Realizable { func isReal() -> Bool { return self.getLogicValue() } } func countReal<S:Collection>(x: S) -> S.IndexType.DistanceType { return countElements(x) } func countReal<S:Collection where S.GeneratorType.Element:Realizable>(x: S) -> Int { return countElements(filter(x,{$0.isReal()})) }
这就是说,如果我通过一系列“可实现”的东西,然后根据他们的规则进行过滤。否则,只要算它们。虽然我可能不会真的使用这个功能(这似乎非常特殊),这个概念很有用。后来的呼叫者可以添加新的“可实现”类型,而不需要修改任何代码(甚至知道它们的实现方式)。这表明如何为不实现协议的事物设置默认行为。
BTW,我在这里使用集合只是因为它们更容易计数(并且我对返回类型有点马虎;注意一个是DistanceType,另一个是Int)。在类型基于集合的函数上获取类型仍然是棘手的(通常会导致编译器崩溃)。我怀疑这将在下一个betas中都有所改善。