Anyone have any more? I'm curious what people come up with for goroutines/channels.
Anyone have any more? I'm curious what people come up with for goroutines/channels.
Go will not inline a function that exceeds complexity metrics, and one of those metrics is whether the function contains a range statement. You will get a real heap-allocated closure invocation on each loop.
Go's function calls are not that cheap, and these will be measurably slower than the for-loop equivalent. I see functional idioms as being a huge risk factor for Go.
True, but:
> and one of those metrics is whether the function contains a range statement. You will get a real heap-allocated closure invocation on each loop.
I think this is no longer true in Go 1.18, see https://github.com/golang/go/issues/14768#issuecomment-98175... .
it := GetAnIterator()
for it.Next() {
it.Value()
}
This still allows composition of different iterators, for building up lazy/incremental processing.https://github.com/johan-bolmsjo/gods/tree/v2
It's not much, only a simple list and an AVL tree that I've carried with me for many years. Binary search trees are useful to solve some problems because they are ordered.
I was impressed with how polished the tools where. The go-lsp plugin just worked with the new generic types. I solved all compiler errors in the editor without actually compiling anything. Did not expect that level of polish. The modules introduction broke the editor integration for many release cycles. This seems much smoother.
It contains generic implementations of
Any
All
Count
Filter
ForEach
Map
Reduce
ReduceRight
Sum
ChunkEDIT: Superior for most non-performance sensitive use cases, that is.
For people not familiar with "monadic async", it's the formal way to refer to the function coloring problem [1]. Monads offer you ways to "lift" your functions/values in the monadic world (paint the blue values red), but you can't do the opposite (paint the red functions/values blue).
[1]: http://journal.stuffwithstuff.com/2015/02/01/what-color-is-y...
It is obvious that a channel is not the same thing as a promise. They are quite different in many ways. But the problems that you solve with promises in some languages are solved with channels in Go. There's pros and cons to each, but the cons of channels aren't all that significant in the specific context of Go and there are some compelling pros to the channels in the specific context of Go, so there isn't a very fertile space left over for a promise library. I've already seen half-a-dozen go by (non-generic, but missing generics aren't the problem) and those are just the ones that get posted to reddit.
I advise writing Go in Go, and not Javascript in Go. But it's your codebase.
(Promises are basically an inner platform [1] for functionality not provided by the base language. Go provides the requisite functionality in the base language. I think I'm more hostile to inner platforms every year, but at least when you're adding capabilities to the base language you can't get any other way there's a debate to be had. Adding an inner platform to get functionality that already exists is just a bad plan.)
What you said is accurate in the context of Go though. Having promises in Go will create an "inner platform". If one wants to nitpick, there may be certain workloads that would perform better with async functions and promises, but the design philosophy of Go would happily trade a small amount of performance for simplicity.
That's fair, and I will try to update my internal mental model and stop unconditionally referring to them as such. Thank you.
(My primary objection to them is the way they throw away the stack and throw away structured programming as a result, but they're at least less bad if they aren't also an inner platform. :) )
Structured concurrency is orthogonal to whether you're using a thread-based or monadic API. Goroutines, for example, are both thread-based and unstructured. On the other hand, you can have concurrency that is structured but still thread-based (like Trio), unstructured but monadic (like Scala's built-in Future type), or both structured and monadic (like Rust's Future type).
> Asynchronous and synchronous code cannot always be combined freely. For instance, you can't directly call an async function from a sync function.
Same with JavaScript from [2]:
> The await operator is used to wait for a Promise. It can only be used inside an async function within regular JavaScript code; however it can be used on its own with JavaScript modules.
In JS, the promise world is a different world. Exceptions won't work like they usually do for example.
[1]: https://rust-lang.github.io/async-book/01_getting_started/03...
[2]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...