- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我从一本书中得到这个,这段代码用在 didSet 方法中,我很困惑为什么当你可以编写一个调用函数 slowdown() 或函数 speedup() 的函数时这会有用?这基本上是声明一个“变量函数”并“将其设置为等于它自己的定义”然后返回一个“函数”? (如我错了请纠正我)。当我可以创建一个函数时,为什么需要使用变量并将其设置为等于定义?那有什么用呢?
最佳答案
当您开始了解函数字面量、获取和返回其他函数的函数以及保存函数的变量时,各种新模式就会出现。这是编程中最强大的工具之一。
您的描述不太正确。它不是“将它设置为等于它自己的定义”。它将函数视为值,就像整数、 bool 值或结构一样。当您将一个函数视为一个值时,您可以组合函数,就像组合其他值一样。这非常强大。
让我们考虑一个基于您的非常基本的示例:
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
来处理这个问题。 twice
不关心我们是否传递了 speedup
或 slowdown
或我们将来可能发明的其他函数。我们有多种方法可以扩展此代码,而无需重写任何可用的原始代码。我们可以访问高阶函数,例如 twice
。这些函数接受或返回其他函数,它们非常强大。在 Swift 中,它们包括 map
和 filter
之类的东西,它们都与创建文字函数并将它们分配给事物的能力相关。
让我们更进一步。不要太担心这段代码中的所有想法,只要担心它允许我们做什么。
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
的函数,因为“重试一定次数,但仅针对某些类型的错误,并且不会太多次”是一个非常复杂的问题,与重试的内容无关.我创建了记录对其他函数的调用的函数,这对于一致的日志记录非常方便。我有执行身份验证的 HTTP 请求处理程序,然后包装 other 做代理的 HTTP 请求处理程序,包装 other HTTP 请求处理程序......这就是功能组合的方式有效,它可以真正改变您编写程序的方式。
而且,在最简单的情况下,这让我们可以进行回调。所以这时不时会出现……
关于swift - 在 Swift 中声明函数类型的变量有什么意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32417653/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!