为什么这个函数的参数仍然是一个元组?

时间:2016-03-01 23:47:22

标签: swift

我对词典有一个扩展,添加了mapflatMapfilter。在大多数情况下它是可用的,但我对如何指定转换和谓词函数的参数感到不满。

首先,扩展本身:

extension Dictionary {
    init<S:SequenceType where S.Generator.Element == Element>(elements: S) {
        self.init()

        for element in elements {
            self[element.0] = element.1
        }
    }

    func filter(@noescape predicate:(Key, Value) throws -> Bool ) rethrows -> [Key:Value] {
        return [Key:Value](elements:try lazy.filter({
            return try predicate($0.0, $0.1)
        }))
    }
}

现在,由于predicate参数被声明为predicate:(Key, Value),我希望以下内容能够正常工作:

["a":1, "b":2].filter { $0 == "a" }

然而,我必须实际使用:

["a":1, "b":2].filter { $0.0 == "a" }

这有点令人困惑,因为声明意味着当谓词实际上作为单个元组参数传递时,有两个参数,而不是2个值。

显然,我可以将过滤器函数声明更改为单个参数(predicate:(Element)),但我真的更喜欢它采用两个明确单独的参数。

关于如何实际获取函数以获取两个参数的任何想法?

2 个答案:

答案 0 :(得分:2)

当您使用没有类型声明的闭包时,编译器必须推断出类型。如果您只使用$0而不是$1,则编译器会认为您只使用一个参数声明了闭包。

此闭包无法与您的filter函数匹配。简单修复:

let result = ["a":1, "b":2].filter { (k, _) in k == "a" }

现在还要记住,元组可以传递给函数并自动匹配参数:

func sum(x: Int, _ y: Int) -> Int {
   return x + y
}

let params = (1, 1)
sum(params)

然后可以通过类型推断来解释["a":1, "b":2].filter { $0.0 == "a" }的行为。有两种可能性,编译器只是选择了错误的一种,因为它认为你只想要一个带有一个参数的闭包 - 而且这个参数必须是一个元组。

答案 1 :(得分:0)

您可以添加比较功能,以便比较Dictionary.ElementKey

func ==<Key: Hashable,Value>(lhs:Dictionary<Key,Value>.Element, rhs:Key) -> Bool {
  return lhs.0 == rhs
}