在Swift中声明函数类型变量有什么意义?

时间:2015-09-05 21:03:59

标签: swift function variables

enter image description here

我从一本书中得到了这个,这个代码用在了didSet方法中,我很困惑为什么当你能编写一个调用函数slowdown()或函数speedup()的函数时这会有用呢?这基本上是声明一个“变量函数”和“将它设置为等于它自己的定义”然后返回一个“函数”? (如我错了请纠正我)。当我可以创建一个函数时,为什么需要使用变量并将其设置为等于定义?有用的是什么?

1 个答案:

答案 0 :(得分:5)

当你开始学习函数文字,获取和返回其他函数的函数以及保存函数的变量时,会打开各种新模式。这是编程中最强大的工具之一。

您的描述并不完全正确。它不是"设置它等于它自己的定义。"它将函数视为值,就像整数,布尔值或结构一样。当您将函数视为值时,您可以组合函数,就像组合其他值一样。这非常强大。

让我们考虑一个基于你的非常基本的例子:

var speed = 0
func speedup() { speed++ }
func slowdown() { speed-- }
var changeSpeed = speedup

speed // 0
changeSpeed()
speed // 1
好的,好的。但正如你所说,我们可以设置一个bool或其他东西,只是做了我们想做的事情。但是,让我们进一步说明:

func twice(f: () -> Void) -> (() -> Void) { return { f(); f() } }

这是一个函数,它接受一个函数并返回一个新函数,它执行第一个函数两次。再读一遍,并考虑一下。它是一个函数,它接受一个函数,并且该函数所做的任何。我们不关心这个功能是什么。我们可以加倍。

因此,让我们改变功能的两倍:

changeSpeed = twice(changeSpeed)
changeSpeed()
speed // 3

我们没有必要修改speedup来处理这个问题。如果我们通过twicespeedup或我们将来可能发明的其他功能,slowdown并不在意。我们可以通过各种方式扩展此代码,而无需重写任何正常工作的原始代码。我们可以访问更高级的函数,例如twice。这些是获取或返回其他功能的功能,它们非常强大。在Swift中,它们包含mapfilter之类的内容,它们都与创建文字函数并将其分配给事物的能力联系在一起。

让我们更进一步。不要担心这段代码中的所有想法,只关注它允许我们做什么。

import Darwin

var speed = 0
func speedup() { speed++ }
func slowdown() { speed-- }

var changeSpeed: () throws -> () = speedup

// This funny syntax lets us more easily create a function that takes a 
// function and retries it some number of times. It's called "currying".
// But the point is that calling `retry` will create a new function that
// retries the given function.
func retry(n: Int)(_ f: () throws -> Void)() rethrows {
    for _ in 1..<n {
        do {
            try f()
            return
        } catch {
            print("It failed. Let's try it again!")
        }
    }
    // One last try. If it fails, so we do we
    try f()
}

struct FailedError : ErrorType {}

// Similarly, `maybe` takes a function and might choose not to run it
func maybe(p: Float)(_ f: () throws -> ())() throws {
    if Float(arc4random())/Float(INT32_MAX) < p {
        try f()
    } else {
        throw FailedError()
    }
}

// With that, we can create a function called "lotsOfTries" that tries
// other functions 10 times. Yes, we're creating a function with `let`.
let lotsOfTries = retry(10)

// And we can create a function that fails other functions most of the time.
let badChance = maybe(0.15)

// And then we can glue them all together without knowing how they work internally.
changeSpeed = lotsOfTries(badChance(speedup))

do {
    try changeSpeed()
    print(speed)
} catch {
    print("Couldn't do it, sorry")
}

所以,一旦你真正接受这种编码,那些就是你可以构建的功能。在我自己的代码中,我使用类似于retry的函数,因为&#34;重试了几次,但仅针对某些类型的错误,而不是太多次&#34;是一个非常复杂的问题,与重审的内容无关。我创建了记录其他函数调用的函数,这对于一致的日志记录非常方便。我有执行身份验证的HTTP请求处理程序,然后包装执行代理的其他 HTTP请求处理程序,这些处理程序包含其他 HTTP请求处理程序....这就是功能组合有效,它可以真正改变你编写程序的方式。

而且,在最简单的情况下,这可以让我们做回调。所以这时不时出现......