如何通过引用传递函数

问题描述 投票:0回答:4

我正在尝试解决这个练习:

创建一个接受整数数组的函数,该函数通过引用传递,将对数组执行操作并返回 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

这是引用传递吗?由于这有效,我不确定这是否正确。

我做错了什么?

function swift pass-by-reference
4个回答
1
投票

首先,通过引用传递 (

inout
) 适用于以下情况:例如,您需要分配给被调用函数内的参数,并将其分配给调用作用域中传递的变量,或者您需要调用
 mutating
方法并使其反映在调用范围等中。

您没有分配给

f
内的
test
。因此,将其设为
inout
是没有意义的,因为它限制了可以传递给它的内容。

要从技术上回答为什么会出现错误,答案是您不能通过引用传递常量变量(即

let
),并且
counter
是常量变量(您不能分配给
counter
)。您可以将用于在顶层定义函数的
func
语法视为类似于带有闭包表达式的
let

func counter(start:Int)->String{ ... }

就像

let counter : Int->String = { (start:Int)->String in ... }

1
投票

如果参数和返回类型匹配,则按原样传递函数。

您根本不需要

&...


0
投票

编译器告诉您

inout f:(Int)->String
与您的
counter()
函数的函数类型不同。如果您从
inout
函数中删除
test
关键字以及函数调用中的
&
,则一切正常。

您确定练习不是要求您通过引用传递数组吗?


0
投票

自从这个线程受到喜爱以来已经有一段时间了,它的答案有点过时了(使用已弃用的 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 中,它运行起来非常容易

© www.soinside.com 2019 - 2024. All rights reserved.