|
TooMuchAbstraction posted:I fail to see how this is any worse (or better) than the Go equivalent: This is a pretty big problem in Go, also see: https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully. Being able to annotate errors is very useful to make them descriptive and human-readable, but programmatically dealing with an error, you want to be able to dig down to what really caused it to initially happen, perhaps in the form of a stack trace. The error interface in general has a lot of flaws as the main mechanism for error handling. It provides a good basic method set and leaves the rest to implementations of error to handle these details. I thought we might have gotten a proposal in for Go1.9 about this, but it didn't happen.
|
# ? Sep 21, 2017 18:20 |
|
|
# ? Jun 5, 2024 05:11 |
|
Coffee Mugshot posted:I don't why people refer to Rob Pike so much when he hasn't worked on the project for like a year at this point. Are you feigning confusion here or are you really in that much of a bubble? Rob Pike was the public face of Go for most of the language's public existence.
|
# ? Sep 21, 2017 19:16 |
|
quote:I was working at Google when Go started to come out, and this was exactly the response I got from Rob Pike when I asked about error handling.
|
# ? Sep 21, 2017 19:36 |
|
KernelSlanders posted:What "unequivocally better solution" are you referring to? pattern matching over algebraic data types
|
# ? Sep 21, 2017 19:45 |
|
One imperative alternative to go's error handling that doesn't use exceptions is the way Rust does it with sum types. In Rust, errors are expressed as Result<TSuccess, TError>. A value must either be a success or a failure. These states are mutually exclusive. You are forced by the language to handle both cases. You cannot forget the error situation if you want access to the success value. A return value that may have an error has a different type than a return value that cannot have an error. If you change a function return signature to return an error when it did not before, the compiler will let you know all of the call sites that are now broken as a result. You cannot have garbage non-sense values that you are by convention supposed to ignore like in Go. Rust also has syntactic sugar for the common case of just propagating the error up the call stack. https://doc.rust-lang.org/book/second-edition/ch09-02-recoverable-errors-with-result.html code:
|
# ? Sep 21, 2017 19:47 |
|
Rust does also have an exception-like mechanism called panics, but these are intended for non-recoverable errors that are not intended to be handled by a caller (divide by zero, out of memory, accessing an array out of bounds, etc.). Usually these errors signal non-recoverable bugs in the program.
|
# ? Sep 21, 2017 19:50 |
|
Obviously we need to bring back restarts
|
# ? Sep 21, 2017 20:04 |
|
comedyblissoption posted:One imperative alternative to go's error handling that doesn't use exceptions is the way Rust does it with sum types. In Rust, errors are expressed as Result<TSuccess, TError>. A value must either be a success or a failure. These states are mutually exclusive. You are forced by the language to handle both cases. You cannot forget the error situation if you want access to the success value. A return value that may have an error has a different type than a return value that cannot have an error. If you change a function return signature to return an error when it did not before, the compiler will let you know all of the call sites that are now broken as a result. You cannot have garbage non-sense values that you are by convention supposed to ignore like in Go. F# encourages this method too; it really does give you a feeling of confidence in the code that you don't get with exceptions - you can see explicitly in your code exactly where things can go wrong and how they have been handled, as opposed to thrown exceptions that might have occurred somewhere nested N functions deep. I haven't really paid attention to Rust, but this is enough to make it my next language to learn - at least over Go anyway. TheBlackVegetable fucked around with this message at 20:48 on Sep 21, 2017 |
# ? Sep 21, 2017 20:45 |
|
See? Clearly if you find Go difficult or cumbersome you're just a fuckin pussy
|
# ? Sep 21, 2017 22:55 |
|
Plorkyeran posted:Are you feigning confusion here or are you really in that much of a bubble? Rob Pike was the public face of Go for most of the language's public existence. I'm feigning confusion because someone referenced Rob Pike getting his head out of his rear end for something something generics implementation in Go2 and he has nothing to do with that except for text snippets on the internet that have been around for a decade. It's really weird to engage with that, honestly. If you dislike Go because Rob Pike was an rear end in a top hat, it's unlikely you've had enough time to actually consider reasonable applications of the language.
|
# ? Sep 21, 2017 23:15 |
|
JewKiller 3000 posted:pattern matching over algebraic data types I hope you write code that's less obtuse and snarky that your posts. Spell it out for us that are too daft to understand how simple it is.
|
# ? Sep 21, 2017 23:17 |
|
Coffee Mugshot posted:I hope you write code that’s less obtuse and snarky that your posts. Spell it out for us that are too daft to understand how simple it is. comedyblissoption posted:One imperative alternative to go’s error handling that doesn’t use exceptions is the way Rust does it with sum types. In Rust, errors are expressed as Result<TSuccess, TError>. A value must either be a success or a failure. These states are mutually exclusive. You are forced by the language to handle both cases. You cannot forget the error situation if you want access to the success value. A return value that may have an error has a different type than a return value that cannot have an error. If you change a function return signature to return an error when it did not before, the compiler will let you know all of the call sites that are now broken as a result. You cannot have garbage non-sense values that you are by convention supposed to ignore like in Go.
|
# ? Sep 21, 2017 23:22 |
|
I see, you're just talking about variant types in general being used for errors. Probably wouldn't work well with Go interfaces if one of the variants is an interface itself. How does rust handle this?
|
# ? Sep 21, 2017 23:30 |
|
Coffee Mugshot posted:I see, you're just talking about variant types in general being used for errors. Probably wouldn't work well with Go interfaces if one of the variants is an interface itself. How does rust handle this? code:
code:
The Box just indicates that you have a "smart pointer" to the trait. The Box is a smart pointer to some data. The Box is necessary because of the way Rust requires you to be explicit about the size of values on the stack. Since a trait's concrete type could be of variable size, the data of the actual type implementing the trait will live on the heap. You need to use Box to be explicit about this in Rust.
|
# ? Sep 22, 2017 00:08 |
|
Coffee Mugshot posted:If you dislike Go because Rob Pike was an rear end in a top hat, it's unlikely you've had enough time to actually consider reasonable applications of the language. Disliking a language because one of its loudest designers is a shithead is actually entirely reasonable.
|
# ? Sep 22, 2017 00:51 |
|
Asymmetrikon posted:Disliking a language because one of its loudest designers is a shithead is actually entirely reasonable. It's not reasonable, but it is very satisfying. For me, Rails.
|
# ? Sep 22, 2017 02:44 |
|
I'm a pretty big fan of explicit error values like in Rust but the one problem with them, like was mentioned upthread, is stack traces. I know that the error-chain crate which does a lot of macro hackery to make error management easy also generates backtraces, which seems nice, but I've never used it in anger so I have no clue how well it works in practice.
|
# ? Sep 22, 2017 04:43 |
|
vOv posted:I'm a pretty big fan of explicit error values like in Rust but the one problem with them, like was mentioned upthread, is stack traces. I know that the error-chain crate which does a lot of macro hackery to make error management easy also generates backtraces, which seems nice, but I've never used it in anger so I have no clue how well it works in practice. Can you manually create a StackTrace object in Rust? In F#, Result<'success, exn> or Result<'success, SomeExceptionSubClass> is a somewhat common pattern when the error is exogenous (like I/O or data errors, as opposed to business logic errors like WidgetNotFound) and so you aren't going to define your own specific error type, because you would have to start by catching an exception anyway. The Exception object then includes its own stack trace.
|
# ? Sep 22, 2017 09:21 |
|
I haven't looked too deeply into how error-chain implements backtraces so I don't really know, sorry.
|
# ? Sep 22, 2017 09:33 |
|
Manually-propagating errors codes on almost every function is definitely a sign that the language isn't supporting something that it should (and that the designers are too comfortable with C). It is essentually forcing the programmer to accept two return values every function invocation: success, failure (oh hey, SICP amb-eval) Reduction ad absurdum: you do not ask programmers to manually prepare and clean up the stack for a function call.
|
# ? Sep 22, 2017 10:24 |
|
This week on hardware horrors: the creeping realisation that if we can't use the product we made, customers might not be able to either. No six figure fuckups this time because it's seven figures.
|
# ? Sep 22, 2017 11:51 |
|
I come from a numerical computing background so my bread and butter are C and Fortran (and lately C++ and Python) so I have no idea what error handling is and in fact I'd rather not have my compiler or interpreter handle errors for me. I want my compiler to produce code that is true to what I wrote with exceptions to automatic optimizations, which I will request iff I want, and no funny business going on under the hood. If there are errors it should either segfault when appropriate or return error codes and exit instead of making any assumptions about what it thinks I intended. Anyway that's my story.
|
# ? Sep 22, 2017 14:30 |
|
My experience with C is that an error is just as likely to silently return bad data without you knowing that anything went wrong until much later, if at all. That seems like a way worse outcome than ... basically anything else. For what it's worth, the default behaviour with exceptions is literally what you describe - "an error happened, let's exit with enough information that the programmer can figure out what happened". If you want any other behaviour, you need to explicitly ask for it.
|
# ? Sep 22, 2017 14:34 |
|
[quote="“Jabor”" post="“476647848”"] My experience with C is that an error is just as likely to silently return bad data without you knowing that anything went wrong until much later, if at all. That seems like a way worse outcome than ... basically anything else. [/quote] So you create some verification and validation test cases with well defined inputs and known, exact, outputs. It's not rocket science, but it could be if that's what you're simulating.
|
# ? Sep 22, 2017 14:36 |
|
Error handling is what you do when you want your program to do something other than fail with an obscure error when there's a problem OP It's for people who write software that they expect other people use out in the world
|
# ? Sep 22, 2017 14:38 |
|
Boris Galerkin posted:So you create some verification and validation test cases with well defined inputs and known, exact, outputs. It's not rocket science, but it could be if that's what you're simulating. Are you one of those dudes who was writing code for fMRI machines?
|
# ? Sep 22, 2017 14:42 |
|
[quote="“Jabor”" post="“476648054”"] Are you one of those dudes who was writing code for fMRI machines? [/quote] Nope, I write code to solve the equation Ax = b. It's as thrilling as it sounds
|
# ? Sep 22, 2017 14:46 |
|
Boris Galerkin posted:I come from a numerical computing background so my bread and butter are C and Fortran (and lately C++ and Python) so I have no idea what error handling is and in fact I'd rather not have my compiler or interpreter handle errors for me. I want my compiler to produce code that is true to what I wrote with exceptions to automatic optimizations, which I will request iff I want, and no funny business going on under the hood. If there are errors it should either segfault when appropriate or return error codes and exit instead of making any assumptions about what it thinks I intended. Sometimes people get overly attached to what they're used to.
|
# ? Sep 22, 2017 14:51 |
|
[quote="“Thermopyle”" post="“476648287”"] Sometimes people get overly attached to what they’re used to. [/quote] You haven't lived until you've used an obscure library written in FORTRAN77 that's been "forked" three times with hacked together "it works don't touch this I'm serious" features.
|
# ? Sep 22, 2017 15:06 |
|
Boris Galerkin posted:You haven't lived until you've used an obscure library written in FORTRAN77 that's been "forked" three times with hacked together "it works don't touch this I'm serious" features. Ahh, the good ole days. (haha, who am i kidding, thats happening right now)
|
# ? Sep 22, 2017 15:11 |
|
Boris Galerkin posted:I come from a numerical computing background so my bread and butter are C and Fortran (and lately C++ and Python) so I have no idea what error handling is and in fact I'd rather not have my compiler or interpreter handle errors for me. I want my compiler to produce code that is true to what I wrote with exceptions to automatic optimizations, which I will request iff I want, and no funny business going on under the hood. If there are errors it should either segfault when appropriate or return error codes and exit instead of making any assumptions about what it thinks I intended. What language are you talking about that automatically tries to resolve errors on its own?
|
# ? Sep 22, 2017 15:19 |
|
https://github.com/munificent/vigil
|
# ? Sep 22, 2017 15:29 |
|
Boris Galerkin posted:I come from a numerical computing background so my bread and butter are C and Fortran (and lately C++ and Python) so I have no idea what error handling is and in fact I'd rather not have my compiler or interpreter handle errors for me. I want my compiler to produce code that is true to what I wrote with exceptions to automatic optimizations, which I will request iff I want, and no funny business going on under the hood. If there are errors it should either segfault when appropriate or return error codes and exit instead of making any assumptions about what it thinks I intended. Aaah yes, like in HPC, where segfault is a valid way to handle errors. No kidding, I had a graph-construction library segfault as a way to handle me passing it the wrong node index.
|
# ? Sep 22, 2017 15:45 |
|
Ok now I'm being serious because I don't understand/know: what would you have it rather do? If the node index was out of range then it should attempt to read memory it can't read and crash, that's how I see it. The other options would be "assume user meant to access last index" or "ignore this error and keep going." Both seem like terrible options to me. e: If you say "it should just note the error and exit it gracefully" then well I just don't see the point/how that's different than just segfaulting. It's not like I can do anything about it other than fixing the problem and recompiling/rerunning. Boris Galerkin fucked around with this message at 15:51 on Sep 22, 2017 |
# ? Sep 22, 2017 15:49 |
|
Boris Galerkin posted:I come from a numerical computing background so my bread and butter are C and Fortran (and lately C++ and Python) so I have no idea what error handling is and in fact I'd rather not have my compiler or interpreter handle errors for me. I want my compiler to produce code that is true to what I wrote with exceptions to automatic optimizations, which I will request iff I want, and no funny business going on under the hood. If there are errors it should either segfault when appropriate or return error codes and exit instead of making any assumptions about what it thinks I intended. apparently not, because "making assumptions about what it thinks you intended" is not what people mean by "error handling" good error handling stuff does the same things as "segfaulting when appropriate" or "returning error codes", but in ways that are less prone to, well, error (relying on segfaults for error handling is particularly nuts because segfaults are non-deterministic and any time your program could segfault it could do something horrible and undetectable)
|
# ? Sep 22, 2017 15:56 |
|
Jeb Bush 2012 posted:apparently not, because "making assumptions about what it thinks you intended" is not what people mean by "error handling" Well in my opinion sqrt(2) is an error because the argument is an int and the return is a real. I'd prefer it give me an error outright, rather than assume I meant to do sqrt(2.0), even though I most likely did. I guess stuff like that is mostly what I mean by languages that automatically handle errors for you cause it's an error to me.
|
# ? Sep 22, 2017 16:08 |
|
Boris Galerkin posted:Well in my opinion sqrt(2) is an error because the argument is an int and the return is a real. I'd prefer it give me an error outright, rather than assume I meant to do sqrt(2.0), even though I most likely did. sqrt(2)'s not an error, it should just return 1
|
# ? Sep 22, 2017 16:09 |
|
Boris Galerkin posted:Ok now I'm being serious because I don't understand/know: what would you have it rather do? If the node index was out of range then it should attempt to read memory it can't read and crash, that's how I see it. The other options would be "assume user meant to access last index" or "ignore this error and keep going." Both seem like terrible options to me. The option you actually have in C is "attempt to read some random memory, which might crash or might just silently give you garbage data depending on how lucky you get". So an error handling strategy of "definitively exit" seems (at least to me) like a clear upgrade.
|
# ? Sep 22, 2017 16:11 |
|
[quote="“quiggy”" post="“476650399”"] sqrt(2)’s not an error, it should just return 1 [/quote] I mean how do you take the square root of an integer? Seriously though, if i allocate memory for an array of 1000 ints and then end up with an array of 1000 real then something is wrong.
|
# ? Sep 22, 2017 16:13 |
|
|
# ? Jun 5, 2024 05:11 |
|
Boris Galerkin posted:Ok now I'm being serious because I don't understand/know: what would you have it rather do? If the node index was out of range then it should attempt to read memory it can't read and crash, that's how I see it. The other options would be "assume user meant to access last index" or "ignore this error and keep going." Both seem like terrible options to me. One reason to do error handling in scientific codes so that you can know where the error is instead. For example, LAPACK logs a message and halts: quote:http://www.netlib.org/lapack/lug/node119.html Granted, it doesn't have a lot of info: code:
but it's better than some (like, for example, opencv).
|
# ? Sep 22, 2017 16:16 |