On the proliferation of try, and soon, await (2020)
forums.swift.org
On the proliferation of try, and soon, await (2020)
1–10 of 44 posts
Re: On the proliferation of try, and soon, await (2020)
#2Most of the White House should be executed on the front lawn.
Milley should be drowned into the Potomac.
Blinken should be thrown out of a helicopter.
Re: On the proliferation of try, and soon, await (2020)
#3> Functions that only mutate instances of well-encapsulated types through their public APIs. That includes nearly all functions that are not methods.
> Methods of well-encapsulated types that only mutate non-member instances of other well-encapsulated types through their public APIs.
This is incorrect! Consider the following function (in psuedocode):
func insert(id: Int, object: ThingInSpace) {
ids.update(id);
var location = get_location(object);
locations[id] = location;
var metadata = compute_metadata(object);
metadatas[id] = metadata;
}
If compute_metadata or get_location throw, then even though we're only modifying dictionaries or sets through their public APIs, we can still invalidate an invariant that affects our program correctness. This function is safe if and only if get_location and compute_metadata cannot throw. If they can throw, this should be rewritten as func insert(id: Int, object: ThingInSpace) {
var location = get_location(object);
var metadata = compute_metadata(object);
ids.update(id);
locations[id] = location;
metadatas[id] = metadata;
}
Adding "try" to the original function makes it clear that this function can destroy the invariant of ids, locations, and metadatas, and it needs to be rearranged to be the second function in order for the code to be correct.Re: On the proliferation of try, and soon, await (2020)
#4Here, Swift (it seems) makes an implicit suggestion that a developer keep their error handling tight and bounded. If you don't, the language softly penalizes you with the need to add keywords to be explicit about changed flow. Go does something similar in eschewing try / catch error handling for a single panic / recover system and very explicit error handling via return values (this was a very intentional design to address what the language creators perceived to be common failure modes in code they were maintaining at the time in other languages, see here [https://go.googlesource.com/proposal/+/master/design/go2draf...] for details). In Go, it's harder to make a certain category of mistake, but at the cost of the user writing more code to handle the error path (and assuming the implicit cost that every line of code could introduce a different mistake).
Every language feature in every language we use (static type declaration vs. implicit types with casting, variable predeclaration vs. implicit creation on first write or read, GOTO vs. function calls vs. try/catch vs. continuation passing, etc.) makes these tradeoffs.
Re: On the proliferation of try, and soon, await (2020)
#5The original poster says that these functions can't ever have invariants broken: > Functions that only mutate instances of well-encapsulated types through their public APIs. That includes nearly all functions that are not methods. > Methods of well-encapsulated types that only mutate non-member instances of other well-encapsulated types through their public APIs. This is incorrect! Consider the following function (in…
Re: On the proliferation of try, and soon, await (2020)
#6The original poster says that these functions can't ever have invariants broken: > Functions that only mutate instances of well-encapsulated types through their public APIs. That includes nearly all functions that are not methods. > Methods of well-encapsulated types that only mutate non-member instances of other well-encapsulated types through their public APIs. This is incorrect! Consider the following function (in…
But you broke encapsulation because locations and metadatas have an invariant that must be externally enforced. I don't think that meets the standard of well-encapsulated. If locations and metadatas must be updated together then you should only be able to do it via some method update() that takes location and metadata.
Under the rules laid down by the original poster in the link, functions which only modify well-encapsulated types via their public APIs cannot violate invariants.
My code shows that there are "invariant[s] that must be externally enforced" even in code that only deals with well-encapsulated types via their public APIs. And if you don't have explicit error handling, it isn't obvious that the invariant can be broken.
Re: On the proliferation of try, and soon, await (2020)
#7Multiple explosions in Kabul killing American citizens.
Re: On the proliferation of try, and soon, await (2020)
#8One of the interesting things (IMO) about programming language design is how the designer can choose to make some concepts harder or easier to express, and how those decisions shape the kind of programs that are easy to write with the language. Here, Swift (it seems) makes an implicit suggestion that a developer keep their error handling tight and bounded. If you don't, the language softly penalizes you with the need…
Re: On the proliferation of try, and soon, await (2020)
#9The original poster says that these functions can't ever have invariants broken: > Functions that only mutate instances of well-encapsulated types through their public APIs. That includes nearly all functions that are not methods. > Methods of well-encapsulated types that only mutate non-member instances of other well-encapsulated types through their public APIs. This is incorrect! Consider the following function (in…
But you broke encapsulation because locations and metadatas have an invariant that must be externally enforced. I don't think that meets the standard of well-encapsulated. If locations and metadatas must be updated together then you should only be able to do it via some method update() that takes location and metadata.
Re: On the proliferation of try, and soon, await (2020)
#10One of the interesting things (IMO) about programming language design is how the designer can choose to make some concepts harder or easier to express, and how those decisions shape the kind of programs that are easy to write with the language. Here, Swift (it seems) makes an implicit suggestion that a developer keep their error handling tight and bounded. If you don't, the language softly penalizes you with the need…
I don't know why but for a moment I read this comment in horror imagining language developers implementing telemetry in the compilers and tooling themselves, then relying on them to "improve the experience" by changing the spec every six months.
... a scan of GitHub and feeding keywords and constructs into a couple hoppers would be all the ML you needed for that. ;)
(... I'm joking, but if you're a language designer, this is actually not a terrible idea for figuring out how people use your language "in the wild." What you do with that information will separate wisdom from knowledge).