Autoclosures

autoclosure是一个自动创建的闭包,用于封装作为参数传递给函数的表达式。它不需要任何参数,当它被调用时,它会返回包装在其中的表达式的值。这种语法上的便利可以让你通过写一个普通的表达式而不是显式的闭包来省略函数参数的大括号。

通常调用采用自动屏蔽的函数,但实现这种功能并不常见。例如,assert(condition:message:file:line :)函数为其条件和消息参数采用autoclosure;其条件参数仅在调试版本中评估,并且仅当条件为假时才评估其消息参数。

autoclosure让你延迟评估,因为在你调用闭包之前,里面的代码不会运行。延迟评估对于有副作用或计算成本较高的代码非常有用,因为它可以让您控制代码的评估时间。下面的代码显示了封闭延迟评估的方式。

var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// Prints "5"

let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)
// Prints "5"

print("Now serving \(customerProvider())!")
// Prints "Now serving Chris!"
print(customersInLine.count)
// Prints "4"

尽管customersInLine数组的第一个元素被闭包中的代码移除,但在实际调用闭包之前,数组元素不会被删除。如果闭包永远不会被调用,闭包内的表达式永远不会被计算,这意味着数组元素永远不会被移除。请注意,customerProvider的类型不是String,而是() - > String - 不带参数返回字符串的函数。

当您将闭包作为参数传递给函数时,您会得到延迟评估的相同行为。

// customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: { customersInLine.remove(at: 0) } )
// Prints "Now serving Alex!"

上面列表中的serve(customer :)函数使用一个显式的闭包来返回一个客户的名字。下面的服务(客户:)版本执行相同的操作,但不是采用显式闭包,而是通过使用@autoclosure属性标记其参数类型来采用autoclosure。现在你可以调用函数,就好像它使用String参数而不是闭包。该参数会自动转换为闭包,因为customerProvider参数的类型是用@autoclosure属性标记的。

// customersInLine is ["Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: @autoclosure () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: customersInLine.remove(at: 0))
// Prints "Now serving Ewa!"

过度使用自动遮挡会使您的代码难以理解。上下文和函数名称应该明确表示评估正在推迟。

如果您想要允许转义的autoclosure,请同时使用@autoclosure和@escaping属性。上面的Escaping Closures中描述了@escaping属性

// customersInLine is ["Barry", "Daniella"]
var customerProviders: [() -> String] = []
func collectCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
    customerProviders.append(customerProvider)
}
collectCustomerProviders(customersInLine.remove(at: 0))
collectCustomerProviders(customersInLine.remove(at: 0))

print("Collected \(customerProviders.count) closures.")
// Prints "Collected 2 closures."
for customerProvider in customerProviders {
    print("Now serving \(customerProvider())!")
}
// Prints "Now serving Barry!"
// Prints "Now serving Daniella!"

在上面的代码中,collectCustomerProviders(_ :)函数不是将传递给它的闭包作为其customerProvider参数进行调用,而是将闭包附加到customerProviders数组。数组声明在函数范围之外,这意味着数组中的闭包可以在函数返回后执行。因此,必须允许customerProvider参数的值转义该函数的作用域。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值