7 ms·
> 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
by 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.
- randomdata 2y ago> Your 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. Uh, what? Convention in Go and Rust sees errors be returned. Earlier, when you defined the topic of conversation, which hasn't changed, you even said "In Go or Rust, returning an error is also a “color” that spreads out to the top of the call stack.", so you seemingly knew this at one time. Where did you get the idea that they are taken as input parameters now? > or you need to propagate it upwards Perhaps like you need to propagate email addresses. But that's the "normal color" of a function. If that is all you are doing, there is no secondary color. That's just "normal" use of a function. async/await, and perhaps even "?", are not "normal" as they introduce to the caller dependencies on functions the caller didn't even call. This breaks the "black box" nature of a function, seeing implementation details leak, thereby no longer guaranteeing that a function is "black" and thus establishing functions that are of other "colors". > When you use this kind of passive-agressive tone, don't be surprised if a charitable reader simply discards it Oh, I wasn't surprised. It was clear from your first comment that your emotions aren't letting you think straight.