You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Global constants and variables are always computed lazily, in a similar manner to Lazy Stored Properties. Unlike lazy stored properties, global constants and variables don’t need to be marked with the lazy modifier.
However, at least in some cases, that appears not to be true. Take this simple example. Assume `processAgeInSeconds()` returns the number of seconds since the process was spawned (which on Darwin can be gleaned through the `libproc` APIs):
// global scopeletageString=String(processAgeInSeconds())sleepThenLog()func sleepThenLog(){sleep(10)print("ageString initialized \(ageString) seconds after launch")}
Since the value placed into `ageString` (almost always) ends up being less than ten, it's clear that `ageString` is being initialized prior to its first (and only) use inside `sleepThenLog()`. (This can be confirmed more strictly with breakpoints, but I figured this was more accessible.)
Things get even stranger if you place the call to `sleepThenLog()` before the definition of `ageString`, like this:
In this case, not only does the use of `ageString` inside `sleepThenLog()` not initialize `ageString`; the resultant use of an apparently uninitialized `String` then crashes! This makes sense given what I know, but it also seems very unlike Swift to allow access to an uninitialized value.
Oh, looks like things behave differently if I don't use `main.swift` and avoid expressions-at-top-level. That's subtle! Is there some documentation on how global variables interact with expressions-at-top-level?
Right, unfortunately there's a difference between "top-level globals", which are globals defined at the top-level where you can also evaluate expressions, and globals in regular contexts, that is, not `main.swift`. The difference can also be seen if you take your single swift file, create a `@main` entry-point, and compile with `-parse-as-library`. That will treat the declarations at the top-level like the "regular" contexts.
Not certain if there are plans to fix this so that special documentation is not required, but @etcwilde might know.
Yep, top-level variables are in a weird hybrid state where they live as global declarations, but are initialized sequentially like local variables.
Eventually, I'd like to make them all local variables to the implicit main function that gets generated.
This will ensure memory safety and data-race protection that we don't have today.
It is still a bit subtle if you're thinking of it like a library, but makes more sense if you're treating it like the top-level space in something like Python.
Changing the semantics is source-breaking, so it will have to wait until Swift-6 to become a feature.
Attachment: Download
Environment
macOS v10.15 Catalina (19H1417)
MacBookAir6,2
Xcode 12.4 (12D4e)
Additional Detail from JIRA
md5: 5f959edc50f7b7263045016bb88930f3
Issue Description:
The TSPL book says:
However, at least in some cases, that appears not to be true. Take this simple example. Assume `processAgeInSeconds()` returns the number of seconds since the process was spawned (which on Darwin can be gleaned through the `libproc` APIs):
Since the value placed into `ageString` (almost always) ends up being less than ten, it's clear that `ageString` is being initialized prior to its first (and only) use inside `sleepThenLog()`. (This can be confirmed more strictly with breakpoints, but I figured this was more accessible.)
Things get even stranger if you place the call to `sleepThenLog()` before the definition of `ageString`, like this:
In this case, not only does the use of `ageString` inside `sleepThenLog()` not initialize `ageString`; the resultant use of an apparently uninitialized `String` then crashes! This makes sense given what I know, but it also seems very unlike Swift to allow access to an uninitialized value.
It's possible these are not considered compiler bugs, but if so, then at least it seems like the book should be corrected.
The text was updated successfully, but these errors were encountered: