Earlier quoted context omitted.
Well, this article is about Result types in Swift, and my point is, I think this kind of thing is overkill. It tends to make the learning curve for a new programmer steeper because there's all these extra bells and whistles provided by the language that have to be learnt before you can get going, and then you have sample code and tutorials and so on. Learning and using C was and is a lot simpler than say Swift.
I keep hearing for about 30 years now, how writing correct code in C is just a matter of being good.
The power of Result types in Swift
61–70 of 77 posts
Re: The power of Result types in Swift
#62Earlier quoted context omitted.
I keep hearing for about 30 years now, how writing correct code in C is just a matter of being good.
It's a matter of getting good at it and that takes time and effort, but the end result is far better than not getting good at it and using a more automated, higher level lanuggae to take the easy way out
https://www.cvedetails.com/product/47/Linux-Linux-Kernel.htm...
Re: The power of Result types in Swift
#63Earlier quoted context omitted.
C is in no way typeless. Furthermore, i would expect a well behaved dev to avoid c at all cost.
Well, this article is about Result types in Swift, and my point is, I think this kind of thing is overkill. It tends to make the learning curve for a new programmer steeper because there's all these extra bells and whistles provided by the language that have to be learnt before you can get going, and then you have sample code and tutorials and so on. Learning and using C was and is a lot simpler than say Swift.
Re: The power of Result types in Swift
#64The tricky part of this approach comes when you extend it. Let's say we have two functions and we'd like to combine them and return a third. typealias Handler1 = (Result -> Void) typealias Handler2 = (Result -> Void) func load(addr: Address, then handler: @escaping Handler1) { ... } func lookup(name: string, then handler: @escaping Handler2) { ... } // What would the type of Handler3 be? func loadDefault(then handler…
I think "sum-type errors" are the wrong default. They force you to deal with the bureaucracy of different error types, which is useless because error handling almost never cares about error type. And they don't give you a stack trace, which is a lifesaver for development and debugging. Plain old unchecked exceptions work better. Probably cheaper too, because sum types require wrapping and unwrapping at each step, whi…
I hear this parroted a lot, and I really don't get it. When an exception happens, you can't resume control flow (unless you're in Common Lisp, which has an objectively better system for exceptions than any we use). In that case, you're right that specific type and details don't matter.
But if you get the failure value back as part of the control flow with a precise type then you can actually recover from it. People quote the Erlang philosophy out-of-context suggesting this is Actually Always Bad. It's not! You might want to: provide a default value for a server (bind to 127.0.0.1 or 0.0.0.0), synthesize a default templated configuration file, propose a valid algorithm over a forbidden one in a cryptographic negotiation, etc.
> Plain old unchecked exceptions work better. Probably cheaper too, because sum types require wrapping and unwrapping at each step, while exceptions can be very cheap when not thrown.
I'd be surprised if that was the case. Stack unwinding and introspection looking for handlers is infamously expensive whereas reading fields from a struct on the stack is seldom considered very expensive. Even if you do have an on-heap indirection that breaks locality, it's not like firing off a random class handlers further up the stack is gonna be BETTER for locality. Given that `finally` exists and objects have destructors, an exception up-stack is often a lot more code than it looks like.
Re: The power of Result types in Swift
#65Earlier quoted context omitted.
Didn't the post you are responding to say that? I suspect you didn't read past the example. The problem comes because you have to either use a single error for two parts or deal with a tough explosion of types. No?
There are known solutions to this problem: you can type-erase to a single supertype (e.g. Error/NSError[0]) or convert from the third-party's type to a first-party type[1] for instance. [0] https://developer.apple.com/documentation/swift/error [1] https://boats.gitlab.io/failure/
But as I've said, yeah you can do this. But it's unfortunate because it destroys a lot of information that's useful in the type signature. Haskell does this with exception hierarchies and some clever runtime casting attempts, but even that has ergonomic issues.
What'd be really amazing is if we could get the totality checking of pattern matching but also the composability of exception handlers, and that's what the next generation of error handling primitives are trying to do.
Re: The power of Result types in Swift
#66Re: The power of Result types in Swift
#67Earlier quoted context omitted.
What I found interesting is that if you have a pipe/filter architectural style, your happy path stays completely free of error handling, because when a filter doesn't have a good result, it just doesn't pass any data to the next filter in line. Done! You can then centralize the error handling by having a "stderr"-like output on your filters. When you have a call/return architectural style, you need to return somethin…
I find this concept of a "stderr output" far more complicated. What's next, a "controlling terminal"? Values are much easier to reason about and inspect than functions, so it's better to have simple functions that return complicated values than to complicate the functions themselves.
And you know this how?
> Values are much easier to reason about and inspect than functions
Right, which is why we want to avoid functions as much as possible.
> simple functions that return complicated values than to complicate the functions themselves
Fortunately, these filters aren't functions, so this doesn't complicate them, it makes them simpler.
Re: The power of Result types in Swift
#68Earlier quoted context omitted.
It's a matter of getting good at it and that takes time and effort, but the end result is far better than not getting good at it and using a more automated, higher level lanuggae to take the easy way out
If not even Linux kernel developers with their merge review process and stress tooling are good at it, what to say of the more mundane developer... https://www.cvedetails.com/product/47/Linux-Linux-Kernel.htm... http://openwall.com/lists/oss-security/
Nowadays, everything is done at a high level using some kind of pre-existing framework and the type of code being written is cookie-cutter so none of this applies. Swift belongs to this new age trend in coding,
Re: The power of Result types in Swift
#69This only pushes the responsibility down lower in the stack. Somewhere someone would have to handle a state where we have data and error being nil at the same time.
No it doesn't. This article is specifically about how you can use the Swift type system to prevent that from happening. You get a compile time guarantee that the result will either be data or error.
Re: The power of Result types in Swift
#70Earlier quoted context omitted.
I find this concept of a "stderr output" far more complicated. What's next, a "controlling terminal"? Values are much easier to reason about and inspect than functions, so it's better to have simple functions that return complicated values than to complicate the functions themselves.
> I find this concept of a "stderr output" far more complicated. And you know this how? > Values are much easier to reason about and inspect than functions Right, which is why we want to avoid functions as much as possible. > simple functions that return complicated values than to complicate the functions themselves Fortunately, these filters aren't functions, so this doesn't complicate them, it makes them simpler.
Professional experience.
> Fortunately, these filters aren't functions, so this doesn't complicate them, it makes them simpler.
Functions are at least restricted enough that you can sort of reason about them. If these things are not even functions then there's no hope of ever understanding them.