5 ms·
> I only see his nursery as being useful when you really want your async tasks to complete before the function in which they were dispatched returns. That's far
by scott_s 9y ago
> I only see his nursery as being useful when you really want your async tasks to complete before the function in which they were dispatched returns. That's far from covering every use case of concurrency!
His section "There is an escape" answers this criticism: "The nursery object also gives us an escape hatch. What if you really do need to write a function that spawns a background task, where the background task outlives the function itself? Easy: pass the function a nursery object."
He goes on to explain a bit more, but one of his points is what really ties this abstraction back into the goto discussion: "Since nursery objects have to be passed around explicitly, you can immediately identify which functions violate normal flow control by looking at their call sites, so local reasoning is still possible."
> A lot of the value of concurrency is in background operations. These simply can't be tied to the duration of a function call on the dispatch thread.
I think they can: applications with background threads would have an outer-level nursery at whatever "main" is for them, and that nursery would be passed into whatever function needs to spawn a background thread.
- jeremiep 9y agoThen what is the difference between the nursery escape and joining a thread or extracting the value of a promise? Both of these will bubble any error back into the dispatch thread. Seems like we're just layering indirections (I wouldn't call that an abstraction) for little added value over the existing constructs.
- scott_s 9y agoThe difference is that you can look at function, see it takes no nurseries as parameters, and know it does not spawn any background tasks. And if it does take nurseries, then you know it's likely that it does.
- jeremiep 9y agoWhats the difference between taking a nursery and returning a promise? Both put the context in the signature, but the later is actually composable.
- scott_s 9y agoWhen I call a function, I have no way of knowing if there are any unhandled promises within it. The difference is the restriction: with nurseries, background tasks can only outlive function calls if the calling function allows them to.
- jeremiep 9y agoI get compile-time warnings or runtime errors when I create unhandled promises. What more is needed?
- scott_s 9y agoNeeded is a strong word, but what this provides are guarantees when reading the code. Much like you know that control flow will come back to the function you're reading after calling another function. We didn't need to know that control flow will resume in the calling function, but it turned out to be very useful.
- jeremiep 9y agoWhat guarantees? Nothing prevents a function receiving a nursery from not using it. Unless the language can enforce it you don't really gain anything valuable over returning a Promise, except more complex code that doesn't compose. > Much like you know that control flow will come back to the function you're reading after calling another function. What about continuations? Exceptions? Aborts? setjmp()? I can think of many cases where control doesn't return to the caller that are perfectly valid. Basically, either the code is so simple theres obviously no bugs, or the code is so complex theres no obvious bugs. I feel a nursery is closer to the later than the former.
- yoz-y 9y agoCan you force explicit nursery passing though? One might make a global nursery object and then just rely on that.
- stouset 9y agoYou might want to consider that this exact thread of questioning does not deviate at all from the similar line that was used to defend `goto` against structured programming. I’m not saying that you’re wrong or that this is necessarily the same thing, but the author addresses these kinds of questions through analogy to the `goto` debate in the article. It’s worth thinking about their similarity. TL;DR, this doesn’t add expressive power (in fact, it removes it). The author argues that the power removed is power that is unnecessary, dangerous, and inhibits the ability to infer higher-level invariants about your programs that can improve understandability while potentially enabling even better abstractions. Even more briefly: restrictions make your code better.
- jeremiep 9y agoI agree, but I still wouldn't call a nursery an abstraction; its an indirection, and a mutable one at that. I also disagree with the goto analogy; concurrency and control flow are two distinct things, they have much more differences than similarities. Implementing a promise as a monad will yield all the same benefits while also keeping the ability to compose and be immutable; and then you have an abstraction and the result is simple. I agree restrictions make the code better, this just isn't one of these cases to me.