Earlier quoted context omitted.
Go does not force you to think about errors at every single point. If a function returns only an error (such as, for example, os.Mkdir), the language will happily let you drop the error on the floor.
And that's totally fine. I don't always want to be fighting with monads. If I did I'd write Haskell code. Go is the quick and dirty git-er-done tool that provides quite a bit more performance and type safety than Python, but maintains some of the development speed/ergonomics. Here's the thing, some of us don't want Rust. It looks great! It's perfectly awesome for it's primary domain (i.e. re-implementing critical por…
Declined Proposal: A built-in Go error check function, “try”
201–210 of 425 posts
Re: Declined Proposal: A built-in Go error check function, “try”
#202Earlier quoted context omitted.
>So long as we can all agree that it feels super bad, I guess this is fine. Actually, I don't think everyone agrees it feels super bad. I personally like having all of my error handling be explicit, painfully explicit even. >approaches the Java world back with checked exceptions where principle trumped ergonomics. I also have to disagree here. To me, checked exceptions are the worst of both worlds. Here you have addi…
> Go doesn't even really force you to check your errors, it just makes it harder to accidentally not check them. Like: I dislike it because it does the opposite, it makes it too easy to accidentally continue execution when there is an error: doThing(); // Error doOtherThing(); Which isn't possible with Exceptions. The only thing that would signal that error handling is missing is the absence of boilerplate to handle…
But I agree, the fact that Go allows this is bad, imo. It would be better if you had to explicitly suppress errors, even with something like this "_ = doThing()" just to make it harder to miss.
Re: Declined Proposal: A built-in Go error check function, “try”
#203GoLand gets around this somewhat by adding in the Live Template of "err" being a macro expansion for the if err != nil { return }. However, it still adds those 3 lines below each requisite call.
If they added a new keyword that took the place of this macro, would that be too intrusive? Clearly, this only works if you have named return values.
It would be nice if there was a bash/Ruby-like chaining, such as:
var1, var2, var3, err := call1(args) &&
var4, var5, var6, err := call2(args) &&
... and more calls and so on ...
return callN(args)
Where "&&" would perform the if err != nil { return } in-line. Should the first call return a non-nil error as the last argument, flow would be returned to the caller. If not, the flow continues as normal.This could even be extended in the case of function chaining:
return call3( call2( call1(args) && ) && )
The downside of using && is that it's overloading the && and may cause some compiler/developer confusion. This was just an example based on a familiar use case (bash); another token can be used.Rasky suggested something like this based on another proposal in the thread, but using "?" instead.
Another way to approach this might be an overlay language analogous to Kotlin. There could be a Go dialect that compiled into Go that provided this feature. Or, possibly an optional "plugin" for go's compiler that added an intermediate transformation step prior to compilation based on new keywords, but this will frustrate debugging and lead to other surprises. Generators tried to do this, but it doesn't seem to have taken off, from the repos I've read.
Just my 2c
Re: Declined Proposal: A built-in Go error check function, “try”
#204Earlier quoted context omitted.
You can pass functions to functions ( https://play.golang.org/p/XNMtrDUDS0 ). So you can do (sans syntax): ErrorCheckerFunc(fn myParams -> MyFunc(myParams), "message") ErrorCheckerFunc(fn myParams2 -> MyFunc2(myParams2), "message2") etc... and then the actual function: ErrorCheckerFunc(fn myFunc, message){ returnVal, returnError = myFunc(); switchError: case error is foo: print error case error is bar: log error prin…
I'm not clear on what exactly you're trying to represent here, but it looks like something that wouldn't work with Go's type system. ErrorCheckerFunc would need to always have the same return type and accept a function with the same type signature.
Alas, that's obviously completely impossible. Such a thing is beyond the capabilities of us mortal programmers. But maybe one day PL researchers will discover a way. One day...
Re: Declined Proposal: A built-in Go error check function, “try”
#205Earlier quoted context omitted.
I'm not a Rust expert but afaik Rust doesn't enforce error checking since you explicitly need to unwrap(). It's very possible to panic because you forgot to check something. It's similar in Go since you can't compile with unused variable so you need to explicitly discard the error with _. Ex: result, _ := func() This is for multi-value returns, for single value you can even omit the _ https://golang.org/doc/effective…
Having unwrap() in your Rust code is like littering your code base with panic(). It’s not appropriate to use in most production code, but is convenient in prototypes, examples and tests. Your example re Go errors is incorrect. The go compiler allows you to ignore errors in returns without any compiler error. For example err := doThingThatErrs() and doThingThatErrs() are both valid Go code.
Re: Declined Proposal: A built-in Go error check function, “try”
#206Earlier quoted context omitted.
I repeatedly tell people that Go takes twice as long to write and half as long to debug. Unless you write perfect code on the first try, the trade off is probably worth it.
That feels about right, but missing the most important measure, IMO, which is it takes 10-100x less time to read and understand a new codebase.
a = append(a[:i], a[i+1:]...)
That’s the recommended implementation of erase(). After this, is the original object referred to by ‘a’ modified? How can you tell?Let’s pop from a stack:
x, a = a[len(a)-1], a[:len(a)-1]
Did you read that 100x faster than ‘a.pop()’?Now this:
a = append(a[:i], append(make([]T, j), a[i:]...)...)
This is an operation called “expand.” What does it do? It is an honest question, I have no idea.These are completely idiomatic examples taken from the Go wiki. They are not readable.
Re: Declined Proposal: A built-in Go error check function, “try”
#207Earlier quoted context omitted.
Packages extensively using reflect + interfaces together can be a bit of a pain to work through. :/
Absolutely. But those are clear code smells. Any org with competent code review would flag them and kill them before they proliferated.
Re: Declined Proposal: A built-in Go error check function, “try”
#208With try, Go might have been a language I'd have enjoyed using. It's a shame. Right now, I see Go as being anti-abstraction and anti-cleverness, and I'd rather not work on codebases in which the language of choice is designed to deter creativity and encourage monotony. Heavy use of Go is a big negative when I evaluate potential projects to work on.
Go's the perfect language for sharecropping developers.
Re: Declined Proposal: A built-in Go error check function, “try”
#209Curious, are there full-time (or at least Primary) Go developers that are upset by the lack of Try?
Re: Declined Proposal: A built-in Go error check function, “try”
#210Just try writing three Go programs with error handling, then, try other languages! I was pissed at first. However, now I cannot code in any language without overusing try and being scared of each line. Using Go's error handling is actually making your code smarter, I mean, you don't want your code to break with a weird message because of something stupid. The simplest example is adding a default-path whenever I'm rea…
try errors in elixir: with {:ok, val1} handle_notfound_error() {:error, :eperm} -> report_permission_error() _ -> raise("don't worry this process is supervised, let it crash!") end low cyclomatic complexity makes for a nice user experience, and you learn the philosophy of "if it doesn't work, just turn it off and on again". Why be scared? Just let it go. The VM has your back.
func do(a Param) (res Result, err error) {
var aPrime T
if aPrime, err = getResource(a); err != nil && err == RecoverableError {
aPrime = definitelyNoErrorAlternativeGetResource(a)
}
var aPrimePrime T
... // many more steps
return doSomething(aPrimePrimePrime)
}