4 ms·
> You can't extend the concept of "coloring" a function to all possible environment and parameters a function needs to execute. It's not the particular abstrac
by the_gipsy 3y ago
> You can't extend the concept of "coloring" a function to all possible environment and parameters a function needs to execute.
It's not the particular abstraction, it's the concept of two different colors: functions that take or don't take context.Context. Ultimately we do have two colors. Seasoned go devs will have refactored some to the other by drilling through `ctx` or removing it and know exactly what "color" is.
> many libraries "helpfully" spawn goroutines to do a thing and offer a promise-like interface to the results. This is the core antipattern being referred to, which I've seen quite a lot. The resulting API is complexified relative to simply having a function that takes parameters and returns results. If you write such a complex API, an end-user of that API can't uncomplexify it. However, if you write the simple, normal function, an end-user of your API who does want that additional functionality can trivially add it, and moreover, they can add it in whatever other combination of things they may want
Do you not read that as "two colors"?
- jerf 3y ago"Ultimately we do have two colors." If you consider this a color, we don't have two colors. We have millions. As I said, it is not that such a concept would be useless; I use it all the time. But it's not "color" any more. "Do you not read that as "two colors"?" That is in response to a completely different question about the cheapness of goroutines, not coloration. Coloration is much stronger than you seem to be understanding. It is not "oh, this function requires that parameter and that one does not, so they must be different colors". It is that you can't correctly run an async function from within a synchronous one and vice versa in the languages in which these are considered completely different things (which does not include Go). While conversion is ultimately possible, it is expensive and high-consquence. If you have a hard time seeing that because, say, a sync function can "simply" bring up an async execution engine for its async calls and an async function can "simply" spawn an entire OS thread to run sync code and collect the results through a promise, consider nesting such an approach arbitrarily deeply as a deep call stack alternates between async and sync calls, which is 100% realistic. It becomes more clear how high-consequence this is if you remember that such programming language constructs must be able to compose essentially arbitrarily deeply. Context parameters can be satisfied by no-context functions simply by passing "context.Background()", and the result is low-consequence. The code does not come apart at the seams, the code using contexts simply ends up not having any data come from the background (empty) context and the background context will never generate a cancellation event, which is apparently what the caller wants since they are asking for that more-or-less explicitly. If that is not what the caller wants, "ctx, cancelF := context.WithTimout(context.Background(), time.Second)" is also trivially available, correct, and low-consequence. If you define coloration down to this level, you completely lose the entire point of the original essay, which is the high-effort, high-consequence effects of bridging sync and async code. Defining colors down to "This function takes a file pointer, thus it is 'file pointer colored'" is profoundly missing the entire point. The idea of function color is useful precisely because it is limited to only certain high-cost conversions, not spread so thin as to cover literally every function parameter. Contexts aren't very special; it is literally easier come up with one if you don't have one ("context.Background()") than it is to come up with an integer, in which you must actually pick one. It isn't anywhere near special enough to justify being called a "color" any more than a file pointer, or a database connection, or any of hundreds of other resource types, most of which impose more constraints on the code than contexts.
- the_gipsy 3y agoYou are the one trying to include "all things like file pointers" as colors, as a strawman. But nobody is trying to say that. Context is tacked on to goroutines to control async stuff, unlike e.g. filepointers or database-handles. Using context.Background() is fine and great for tests or e.g. some CLI program. But consider deeply nesting functions that all do context.Background(). Go just smudges everything as gray and calls it a day. Edit: what I'm trying to say is that go has not completely solved the colored function problem, which I think is what you're implying.
- burnished 3y agoThat wasnt a strawman, that was an example to help illustrate a point. Also it is a little fun that your smudge metaphor tacitly admits the other person is correct
- the_gipsy 3y ago> A straw man fallacy (sometimes written as strawman) is the informal fallacy of refuting an argument different from the one actually under discussion, while not recognizing or acknowledging the distinction. (Emphasis mine) Yes, go has an async runtime built in, congratulations. It's just not nearly as good as advertised.
- burnished 3y agoOh.. genuinely, thats what you have been doing through this thread
- icholy 3y agoWhat you're actually saying is "I don't understand the colored function problem".
- the_gipsy 3y agoYou're not saying anything.