Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> That constraint can be discharged with `context.Background()` just like the async constraint can be discharged by not `await`ing the future in Rust.

Context isn't a control flow property. Goroutines are still concurrent regardless of whether Context is passed, a global, or whatever, and regardless of whether intermediate functions know anything about Context--they could be calling closures that have captured Context on their own.

Another way of looking at it is that Context is just a way to specify certain properties of messaging objects, not the functions you call. A Context timeout could just as well be set on a socket itself, for example. Await/async is an independent property of the fundamental behavior of each and every function; and a property all functions in a call chain must obey to achieve the desired result.

The "colored functions" debate is just a twist on older debates, such as debates over first-class functions. The definition of first-class functions is instructive. In Go all functions are first-class because, just as in any other language with first-class functions, a reference to a function has the same primitive type regardless of whether it's a closure, is suspendable, etc. The type of its application-defined arguments are irrelevant in this regard. Rust, by contrast, does not have first-class functions in the strict sense, because it has several distinct primitive types for functions; not just for async/await, but notably for closures.

Notably, any language with both first-class functions and closures must be garbage collected. I'm sure there were multiple motivations for Go being garbage collected, but supporting closures as first-class functions is surely one of them, precisely so you don't have a "colored function" problem, where closures are distinguishable from non-closing functions with the same argument and return types.

You can dispute my description and definition of first-class functions (indeed, I skirted the question of whether the distinction between Go functions and methods matters), but at the very least it should elucidate the fundamental issues. Importantly, changes in the type signature of a function because of application-defined argument or return types is irrelevant. What's relevant is whether--or at least the extent to which--internal properties of a function object (e.g. references closed-over values) are visible in the type system, effecting how and when they can substitute for an otherwise identical function lacking the internal property.



You’re correct that they’re fundamentally different things, I didn’t mean to draw a false equivalence between them.

The comparison I was trying to draw between them was the way they infect the call tree and usually demarcate impure functions.

When I said that context.Background() discharges the constraint I meant in the sense that the caller doesn’t need to propagate that argument to its caller as it can just pull a context out of thin air.

However I’ve seen a lot of new go devs confuse context.Background() for forking things into the background.

For what it’s worth, I think coloured functions are actually a good thing. If you’re following clean architecture or something similar coloured functions help you easily distinguish what layer in your application something belongs to.


> Notably, any language with both first-class functions and closures must be garbage collected

This is not true, and Rust is a counter-example.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: