我正在尝试解决这个练习:
创建一个接受整数数组的函数,该函数通过引用传递,将对数组执行操作并返回 Int 结果。
我遇到了问题。经过多次搜索无果后,我将问题分解为代码片段来单独测试每个片段。
我简单的“通过参考代码传递函数”是:
func counter(start:Int)->String{
for var i = 0 ; i<start; ++i{
println("I => \(i)")
}
return "Done"
}
func test(i:Int, inout f:(Int)->String){
f(i)
}
test(5,&counter)
问题是,即使是我通过引用传递函数的简单测试也失败了:
(Int)->String is not convertible to @lvalue inout $T3
如果我这样做:
func counter(end:Int)->String{
for var i = 0 ; i<end; ++i{
println("I => \(i)")
}
return "Done"
}
func test(i:Int, inout f:(Int)->String){
f(i)
}
var f1 = counter
test(5,&f1)//pass a reference as an argument to the function
这是引用传递吗?由于这有效,我不确定这是否正确。
我做错了什么?
首先,通过引用传递 (
inout
) 适用于以下情况:例如,您需要分配给被调用函数内的参数,并将其分配给调用作用域中传递的变量,或者您需要调用 mutating
方法并使其反映在调用范围等中。
您没有分配给
f
内的 test
。因此,将其设为 inout
是没有意义的,因为它限制了可以传递给它的内容。
要从技术上回答为什么会出现错误,答案是您不能通过引用传递常量变量(即
let
),并且counter
是常量变量(您不能分配给counter
)。您可以将用于在顶层定义函数的 func
语法视为类似于带有闭包表达式的 let
:
func counter(start:Int)->String{ ... }
就像
let counter : Int->String = { (start:Int)->String in ... }
如果参数和返回类型匹配,则按原样传递函数。
您根本不需要
&...
。
编译器告诉您
inout f:(Int)->String
与您的 counter()
函数的函数类型不同。如果您从 inout
函数中删除 test
关键字以及函数调用中的 &
,则一切正常。
您确定练习不是要求您通过引用传递数组吗?
自从这个线程受到喜爱以来已经有一段时间了,它的答案有点过时了(使用已弃用的 Swift),所以:
func counter(_ end:Int)->String{
for i in 0..<end {
print("I => \(i)")
}
return "Done"
}
func doCall(_ intParameter:Int, _ function:(Int)->String) {
print("\(function(intParameter))")
}
func testCallByReference() throws {
doCall(5, counter)
}
将其放入 XCTestCase 中,它运行起来非常容易