8 ms·
> It does! In both case you need to "unwrap" the value Just as you do with any value, such as an email address, returned by a function. It is curious that you
by randomdata 2y ago
> It does! In both case you need to "unwrap" the value
Just as you do with any value, such as an email address, returned by a function. It is curious that you avoided my question as it would help us better understand where you are trying to come from. If that is the stance you are trying to take you're not exactly wrong about there still being some sort of dependence – there is an inherit dependency created when calling a function, always - but there is not a different color of dependence found within that. You're missing the intent of "coloring" if that is what you are trying to say.
async/await introduces a different type of dependence than a function would normally present, where the dependence is no longer direct. I may even agree that the "?" operator introduces a similar indirect dependence. But a function returning an email address (or error; the type of the value is immaterial) is the "natural color" of a function. If that is all you have, there isn't a secondary color.
> as soon as you start calling a function that returns an error, you're going to write something that looks like
Only for internet memes. You would never write production code like that for so many reasons.
- littlestymaar 2y ago> you do with any value, such as an email address, returned by a function. It is curious that you avoided my question as it would help us better understand where you are trying to come from I don't understand what you mean with your email address example. If you ask a function for an email address, and you get an email address you don't have to unwrap anything. > You're missing the intent of "coloring" if that is what you are trying to say. I'm not, really. The key thing is that as long as you have some effect (like "an error occurred" or "the execution is suspended while running some IO operation", “this function is allocating”, “this function is impure”, etc.) happening somewhere in the call stack then it infects all the call stack no matter what the language does. (A previously pure function calling an impure one becomes impure, a non-allocating function calling an allocating one becomes allocating itself, etc.) In some language, this effect is visible to the caller by default (but can generally be opted-out) and you have this kind of red/blue split for any effect. In other languages this effect is just hidden (but it still exists on reality), that means less effort annotating your code but also less information when reading other people's code. It's exactly the same tradeoff as typing. > Only for internet memes Not literally like that, but the gist of it still stands, you end up adding an error return value to your functions the vast majority of the time.
- randomdata 2y ago> I don't understand what you mean with your email address example. But you didn't think to ask any followup questions to help with your understanding? > The key thing is that as long as you have some effect [...] happening somewhere in the call stack then it infects all the call stack no matter what the language does. In the same way email addresses do, I suppose. But that is the "natural color" of a function. Consider: fn getEmail() { return "joe@example.com" } fn getPerson() { email = getEmail() return "Joe Blow", email } fn getUser() { name, email = getPerson() return "joeblow123", name, email } fn main() { username, name, email = getUser() print(username, name, email) } Yes, you could say in a sense `getEmail` "infected" `getUser` in its need to get the email address to the top of the stack, but the dependence at each step remains direct. getUser returns an email address because an email address is relevant to the result of `getUser`, not just because it happened to call `getEmail`. That is different to async/await, where `main` now has to become aware of what `getEmail` is doing because `getUser` happened to call it transitively. The dependence is indirect. async fn getEmail() { return background { return "joe@example.com" } } async fn getPerson() { email = await getEmail() return "Joe Blow", email } async fn getUser() { name, email = await getPerson() return "joeblow123", name, email } async fn main() { username, name, email = await getUser() print(username, name, email) } I may be inclined to agree that the "?" operator can introduce a similar indirect dependence: fn producesError() { return ProductionError("an error occurred") } fn doesSomething() { value = producesError()? return true } fn main() { result = doesSomething() match result { ProductionError: print("Error", result) OK: print("OK", ok) } } Like async/await, `main` now has to be aware of what `producesError` is doing without calling it directly. But, then again, much like as we discussed in your Go example, you'd never actually write production code like that. There are so many things wrong with it. So, I'm not sure how significant that coloring actually is. And, regardless, is not related to the original discussion.
- littlestymaar 2y agoYour email address example is backwards: you can indeed get function coloring with just regular functions but its not the return value that causes it, but the input parameters. Consider this: function foo(name){ console.log(`Hello ${name}`); } function bar(name){ foo(name) } function top(user){ bar(user.name) } If the `foo` function at the bottom of the stack needs some additional input (say the email address), then you'll need to pass it down and modify the signature of every function above: function foo(name, email){ sendMail("Hello ${name}", email); } function bar(name, email){ foo(email) } function top(user){ bar(user.name, user.email) } As you can see, "My function needs some particular data" is also an effect that will transitively contaminate the call stack above (in "indirect" manner to reuse your wording). In fact this is already apparent in the original blog post since the first two third are about callback-based concurrency, in which the coloring comes as a function parameter. > But, then again, much like as we discussed in your Go example, you'd never actually write production code like that. There are so many things wrong with it. No matter how you end up writing your code, there is only two alternative: you either address the problem and then you don't have to propagate the error (this is the minority case by a large margin) or you need to propagate it upwards (which happen at least 90% of the time). > So, I'm not sure how significant that coloring actually is. And, regardless, is not related to the original discussion. It is exactly as significant as async coloring. That doesn't mean the problem it causes is big though, the "async coloring problem" is vastly overblown and everybody deals with strictly equivalent "effect problems" all the time without even thinking about it, which was my original argument at the very top of this thread. By the way: > But you didn't think to ask any followup questions to help with your understanding? When you use this kind of passive-agressive tone, don't be surprised if a charitable reader simply discards it, the less charitable thing to do instead would be escalating in aggressiveness.