Example of Actors (Concurrency) errors out

The example shown for the Actors section of the Concurrency chapter of the book, errors out when running it as-is.

Here's the code for the example:

[...] For example, here’s an actor that records temperatures:

actor TemperatureLogger {
    let label: String
    var measurements: [Int]
    private(set) var max: Int

    init(label: String, measurement: Int) {
        self.label = label
        self.measurements = [measurement]
        self.max = measurement
    }
}

...
You create an instance of an actor using the same initializer syntax as structures and classes. When you access a property or method of an actor, you use await to mark the potential suspension point—for example:

let logger = TemperatureLogger(label: "Outdoors", measurement: 25)
print(await logger.max)
// Prints "25"

However, when running this code via the swift command in the terminal, it errors out as shown below:

I managed, however, to make it work—by refactoring the code to access the max property of the actor as follows:

Task {
    let logger = TemperatureLogger(label: "Outdoors", measurement: 25)
    print(await logger.max)
}

In such case, it prints 25, as expected.

/cc @Alex_Martini

The snippet is "right" but only partial I suppose...

The general rule about any await is that it must be inside of an asynchronous closure or function. Task{} creates such closure, but you could also write it as

func x() async { 
    let logger = TemperatureLogger(label: "Outdoors", measurement: 25)
    print(await logger.max)
}

I'm not sure about adjusting the example and have to iterate all the cases where you'd be able to write await.


Above in the document it is explained where you can use await:

Because code with await needs to be able to suspend execution, only certain places in your program can call asynchronous functions or methods:

  • Code in the body of an asynchronous function, method, or property.
  • Code in the static main() method of a structure, class, or enumeration that’s marked with @main .
  • Code in a detached child task, as shown in Unstructured Concurrency below.

So that intends to cover this.

Though that sentence has a bug anyway, we'll fix it (a detached task is not a child task)

I'd agree with @NSMau that it's a documentation bug that the code as-is gives an error. There is no indication anywhere near the example code that it needs to be encapsulated "in" anything else and users should not need to parse the whole document to figure out the unstated rules that will make an example actually compile.

On a related note, though—this is the second time in just a week or two that a user has been unable to figure out how to use concurrency features because top-level code doesn't behave like code in a @main type's main(). In this case, even the reference text elides that difference.

I recall asking in one of the earlier concurrency pitches specifically about this issue (although I can't seem to find that thread any more) where top-level code and code inside a @main type's main() behave differently. I thought it would be a progressive disclosure problem—which is now borne out with the questions on these forums. I remember being satisfied (and again, I can't seem to find that thread anymore) that the intended design was for top-level code to behave no differently than using a @main type's main()—how come that's not the case anymore with concurrency features, and can we fix it?

3 Likes

I don’t disagree, but neither can I do more here than to try to get it fixed (I reached out and hope to get it done). It would be nice if the docs were an open-source page we can PR to, but sadly that isn’t the case.

Re the general issue: there was/is a hope to allow top level code to have async code in it, but that again has not been done — if that were implemented it would have solved the issue here.

I wish I could do more here, but we’ll have to go through the process of updating the book the usual route, and it’s up to the editors to decide if they want to nest everything in Task{} or not… Alex is among the right people to ping here, so things happen after thanksgiving here.

2 Likes