Swift中的初始化和范围

时间:2016-07-22 06:02:57

标签: ios swift xcode macos scope

下面的代码不会被编译,Swift编译器会显示错误:"Variable 'firstVar' used before being initialized"

var firstVar: Double
var secondVar = 2.0

if 1 > 0 {
    firstVar = 2.0
}

print(firstVar)

同时Swift编译器(2.2)对以下代码没有问题,它打印"Hello, Stack Overflow"。对于Swift 3.0,以下代码将按预期显示错误。

var firstVar: Double
var secondVar = 2.0

if 1 > 0 {
    firstVar = 2.0
}

if secondVar > 1.0 && firstVar > 0 {
    print("Hello, stackoverflow!")
}

你能解释一下,为什么第二个代码示例中if语句的第二个条件的计算结果为true,而编译器(Swift 2.2)在第一个代码示例中没有抱怨firstVar被初始化确实如此。

1 个答案:

答案 0 :(得分:1)

通过将表达式包装在一个闭包中来延迟对表达式的求值:Swift playground的即时“编译”的限制让这个错误的程序流程无错误地传递

rhs&&)的= firstVar表达式自动包含在闭包中(此处:使用autoclosure),这意味着firstVar的评估延迟(延迟),这样你的例子将在使用Swift Playground的动态编译时“编译”。我可以推测,在使用Swift Playground时,只有在运行时时才会检查延迟评估的正确性的前提条件,而不是在编译时检查。

在实际项目中尝试相同时,编译器不需要限制自己进行快速动态编译,并且可以发现编译时错误:

  

“错误:变量'...'在初始化之前由闭包捕获”

即,上面不应该编译,但由于firstVar语句正文中if的条件初始化,实际上运行正常。请注意,1 > 0true的事实不应影响这是编译时错误的事实,因为评估1 > 0的状态是运行时决策

<强>详情

逻辑二进制中缀运算符'&&'有一个右侧rhs,它是懒惰实现的,@autoclosure

func &&(lhs: BooleanType, @autoclosure rhs: () -> BooleanType) -> Bool {
    return lhs.boolValue ? rhs().boolValue : false
}

来自The Language Reference - Attributes

  

<强> autoclosure

     

此属性用于延迟表达式的评估   自动将该表达式包装在没有参数的闭包中。   将此属性应用于函数的参数声明或   不带参数且返回类型的方法类型   表达。具有autoclosure属性的声明意味着   noescape也是如此,除非传递了可选的属性参数   escaping

我们可以通过以下示例更清楚地显示您的示例的行为:

var foo: Double

/* use autoclosure to capture the argument in a closure */
func bar(@autoclosure arg: () -> Double) {
    print(arg())
}

/* or let the user explicitly supply the argument in a closure form */
func baz(arg: () -> Double) {
    print(arg())
}

if true {
    foo = 1.0
}

bar(foo)        // 1.0, OK in Playground, error when in a project
baz() { foo }   // 1.0, OK in Playground, error when in a project