yes that is easiest; or just be a 100% owned subsidiary. (that's what say, waymo is).
the good thing is that you afterwards the cap table of the subsidiary or the spunoff can evolve (ex: waymo / amp can raise money independent of the parent company).
Because Sourcegraph is a viable business in its own right. Small companies find it challenging to do multiple things well, and it's normally better for them to spin off promising ideas that aren't directly part of their main product.
I’m not talking as a user, I’m talking as a person who ported 350kLOCs of python from 2 to 3.
Django absolutely would have been ported: it was ported without six by Vinay Sajip (building on an earlier work of Martin von Löwis). In fact a limited shim layer was initially committed based on Vinay’s efforts: https://github.com/django/django/commit/5e6ded2e58597fa324c5...
The team ultimately decided to use and re-export six for the convenience of the ecosystem, not out of any sort of necessity.
I think this is really unfair, in the current day and age, especially when there are "Open Weight Models" that are bending the definition of the FOSS.
I don't have a skin in the game, but I personally think that the definition of FOSS is too rigid and strict and is not evolving. There has been many challenges over time (LGPL's linking exception, tivoization, AGPL trying to fight against SaaS, Open Core business models, ...); and we are really bestowing very harsh moral standards for people who are trying to do the right thing.
For me, Sentry, being 10+ years in its existence (I used it ever since its logo was a Starcraft II unit), never participated in the usual enshitification of the software, being labeled as "NOPE" is disingenuous. I would gladly pay for Sentry because I love the software, and I also know that if shit hits the fan, I can self-host it (though the configuration for self-hosting got progressively difficult over time, but that's the complexity of modern SaaS stack). I can make similar arguments to other tools in this site that I'm familiar with.
FOSS is indeed a moral and ethical stand on freedom, than on business realites (that's more why "open source" came about).
You can't have the FOSS cake and eat it too.
For eg: Sentry can release sentry-open under a fully free license from moral considerations, but choose not to do so because of business considerations. That's an OK choice to make, but you hence don't get to call yourself.
Its ok for things not to be open source, but for the term to mean anything it has to have a definition. Vauge moral handwaving about "doing the right thing" doesn't really help give meaning to the term. A project can be open source and morally bad. It can be closed source and morally good. Authors' moral intentions are a totally orthogonal dimension.
I agree the original setup didn’t allow for much else in the way of references, I just wanted to shoehorn in a perhaps more apropos time travel movie reference.
If you like Primer you might like this Australian time travel movie also, but I don’t think it references 88 MPH either. It’s a kind of Eternal Sunshine vibe and also involves weird tech.
I like `gevent` but I think it may have been too hacky of a solution to be incorporated to the main runtime.
"creating the first ever first-class language with green-threading at its core."
... isn't that what Go is? I think out of all languages I use extensively, Go is the only one that doesn't suffer from the sync/async function coloring nightmare.
I'm with you that function "coloring" (monads in the type system) can be unergonomic and painful.
> ... isn't that what Go is? I think out of all languages I use extensively, Go is the only one that doesn't suffer from the […] coloring nightmare.
Because it doesn't have Future/Promise/async as a built-in abstraction?
If my function returns data via a channel, that's still incompatible with an alternate version of the function that returns data normally. The channel version doesn't block the caller, but the caller has to wait for results explicitly; meanwhile, the regular version would block the caller, but once it's done, consuming the result is trivial.
Much of the simplicity of Go comes at the expense of doing everything (awaiting results, handling errors, …) manually, every damn time, because there's no language facility for it and the type system isn't powerful enough to make your own monadic abstractions. I know proponents of Go tend to argue this is a good thing, and it has merits. But making colorful functions wear a black-and-white trenchcoat in public doesn't solve the underlying problem.
One of the largest problems identified in the original "what color is your function" article ( https://journal.stuffwithstuff.com/2015/02/01/what-color-is-... ) is that, if you make a function async, it becomes impossible to use in non-async code. Well, maybe you can call "then" or whatever, but there's no way to take an async function and turn it into something that synchronously returns its value.
But in Go, it's very easy to do this; you can just do "result := <- ch" to obtain the value from a channel in synchronous code. (This blocks the thread, but in Go's concurrency model this isn't a problem, unlike in JavaScript.) Similarly it's very easy to take a synchronous function and do "go func() { ch <- myFunction() }()" to make it return its result in a channel.
> But in Go, it's very easy to do this; you can just do "result := <- ch" to obtain the value from a channel in synchronous code.
What you call "synchronous code" is really asynchronous. To actually have something that resembles synchronous code in Go you have to use LockOSThread, but this has the same downsides as the usual escape hatches in other languages. This is also one of the reasons cgo has such a high overhead.
Hm. You and parent comment have made me realize something: as much as I dislike how many useful abstractions are missing from Go, async for blocking syscalls is not one of them, since the "green thread" model effectively makes all functions async for the purposes of blocking syscalls. So I retract my "you have to do it manually" comment in this case. I guess that's part of why people love Go's concurrency.
Of course, as you said, stackful coroutines come with runtime overhead. But that's the tradeoff, and I'm sure they are substantially more efficient (modulo FFI calls) than the equivalent async-everywhere code would be in typical JS or Python runtimes.
My "you have to do it manually" comment comes from some other peeves I have with Go. I guess the language designers were just hyper-focused on syscall concurrency and memory management (traditionally hard problems in server code), because Go does fare well on those specific fronts.
I remember this article in 2015 being revelatory. But it turned out that what we thought was an insurmountable amount of JS code written with callbacks in 2015 would end up getting dwarfed by promise-based code in the years to come. The “red functions” took over the ecosystem!
With Python, I’m sure some people expect the same thing to happen. I think Python is far more persistent, though. So much unmaintained code in the ecosystem that will never be updated to asyncio. We’ll see, I suppose, but it will be a painful transition.
All goroutines are async in some sense, so generally you don't need to return a channel. You can write the function as if it's synchronous, then the caller can call it in a goroutine and send to a channel if they want. This does force the caller to write some code, but the key is that you usually don't need to do this unless you're awaiting multiple results. If you're just awaiting a single result, you don't need anything explicit, and blocking on mutexes and IO will not block the OS thread running the goroutine. If you're awaiting multiple things, it's nice for the caller to handle it so they can use a single channel and an errorgroup. This is different from many async runtimes because of automatic cooperative yielding in goroutines. In many async runtimes, if you try to do this, the function that wasn't explicitly designed as async will block the executor and lead to issues, but in Go you can almost always just turn a "sync" function into explicitly async
> I like `gevent` but I think it may have been too hacky of a solution to be incorporated to the main runtime
gevent's monkey-patching might be hacky, but an official implementation of stackful coroutines (similar to Lua's) need not have been.
Instead, stackless coroutines were chosen - maybe on merit, but also maybe because C#'s async/await keywords were in-vogue at the time and Python copied them.
This is the answer; turns out that non-transformed links are the most generic data format, without any "compression" - QR codes or a third-party-intermediary - needed.
Definitely agree that goroutines don't suck; it makes go into one of the only languages without "function coloring" problem; True N:M multithreading without a separate sync and async versions of the IO libraries (thus everything else).
I think channels have too many footguns (what should its size be? closing without causing panics when there are multiple writers), thus it's definitely better "abstracted out" at the framework level. Most channels that developers interact with is the `Context.Done()` channel with <-chan struct{}.
Also, I'm not sure whether the go authors originally intended that closing a channel would effectively have a multicast semantics (all readers are notified, no matter how many are); everything else have pub-sub semantics, and turns out that this multicast semantics is much more interesting.
reply