swift 3: func 作为参数

swift 3: func as argument

我有几个功能:

func x1(_ data: [Double], _ par1: Int, _ par2: Int) -> Double {
…
}

func x2(_ data: [Double], _ par1: Int, _ par2: Int, _ par3: Int) -> Double {
…
}

我想从 [-1 … 100] 测试它们作为 par1, par2, … 所以我必须调用:

x1(data, -1, -1) 
x1(data, -1, 0)
...
x1(data, -1, 100)
x1(data, 0, -1)   
…
x1(data, 100, 100)

func x2(data, -1, -1, -1) … x2(data, 100, 100, 100)

然后比较结果,找出 x1x2 中最大的一个。我如何编写一个函数测试来调用另一个参数数量未知的函数(x1 有 3 个,x2 有 4 个),我该如何调用这个测试函数?

func test(testfunc: (_ data: [Double], _ par: Int…) -> Double, _ data: [Double], params: [Int]…) -> [Int] {
    //?
    return *optimal parameters , for example: [10, 57]
}

我还没有完全理解你的问题,但这可能暗示你的代码太复杂了。尝试将其拆分为多个任务并单独测试每个任务。

基于协议的面向对象方法可能如下所示:

protocol OODouble {
    var value: Double { get }
}

final class ThreeParamDouble: OODouble {
    private let data: [Double]
    private let par1: Int
    private let par2: Int
    init(_ data: [Double], _ par1: Int, _ par2: Int) {
        self.data = data
        self.par1 = par1
        self.par2 = par2
    }
    var value: Double {
        get { /* calculate result (aka x1) here */ }
    }
}

final class FourParamDouble: OODouble {
    private let data: [Double]
    private let par1: Int
    private let par2: Int
    private let par3: Int
    init(_ data: [Double], _ par1: Int, _ par2: Int, _ par3: Int) {
        self.data = data
        self.par1 = par1
        self.par2 = par2
        self.par3 = par3
    }
    var value: Double {
        get { /* calculate result (aka x2) here */ }
    }
}

final class LargestDouble: OODouble {
    private let doubles: [OODouble]
    init(_ doubles: [OODouble]) {
        self.doubles = doubles
    }
    var value: Double {
        get {
            var largestDouble: Double = 0
            (doubles.map { [=10=].value }).forEach {
                largestDouble = largestDouble < [=10=] ? [=10=] : largestDouble
            }
            return largestDouble
        }
    }
}

let largestValue = LargestDouble([
    FourParamDouble(data, -1, -1, -1),
    ...
    FourParamDouble(data, 100, 100, 100)
])
let result = largestValue.value

现在您可以独立于计算 x2 测试 x1 的计算,甚至可以独立测试 'find the largest one' ist。最后一个可以用伪造的协议实现进行测试:

final class OODoubleFake: OODouble {
    init(_ value: Double) {
        self.value = value
    }
    let value: Double
}

正如@Rob Napier 所说,在测试中实现类型安全的唯一方法是为每个 x* 函数设置一个测试函数。但是,如果您可以更改 x* 函数,则有一个 much 更简单的方法:声明一个 single x() 函数采用可变数量的参数:

func x(_ data: [Double], _ pars: Int...) -> Double {
    // Loop through the variable number of pars like this:
    for index in pars { ... }
}

现在您可以使用 任意 个参数调用它,因此:

let maxOf2 = x(data, -1, -1)
let maxOf7 = x(data, 100, 100, 100, 100, 100, 100, 100)

你的测试函数也同样简单:

func test(functionToTest: ([Double], Int...) -> (Double), data: [Double], pars: Int...) -> [Double] {
    return functionToTest(data, pars)
}

使用 typealias:

可能更容易阅读
typealias MaxFunction = ([Double], Int...) -> (Double)

func test(functionToTest: MaxFunction, data: [Double], pars: Int...) -> [Double] {
    return functionToTest(data, pars)
}