> Generics add a lot of value >From a personal point of view with the interfaces I got all the genericity I needed to model solutions, and generics per se doesn't provide a new approach to find solutions. I Mean, you can solve the same old problems with or without generics... Generics provides another way of writing code, just as this proposal to deal with errors. This is my view on this matter.
El vie, 4 ago 2023 a las 10:16, Miguel Angel Rivera Notararigo (< ntr...@gmail.com>) escribió: > It is not just resistance to change, it is about not adding new features > that add more complexity than value. I am pretty sure people will complain > about Go's error handling even if we use "orelse return err". > > Generics add a lot of value, it shows the Go team is open to changes. But > imagine they add any feature people ask, C++ would be simpler than Go. > > As I said, I like the proposal, but I have learned that some times, I have > to accept things are not always as I want them to be. > > On Fri, Aug 4, 2023, 08:58 Victor Giordano <vitucho3...@gmail.com> wrote: > >> As far as I see things there is always room for changes... but changes >> doesn't come without some resistance.. That is natural... >> >> > Go best features is the lack of new features. >> >> What about generics? That was a major change... It was really necessary >> or not is another topic. >> >> El vie, 4 ago 2023 a las 9:47, Miguel Angel Rivera Notararigo (< >> ntr...@gmail.com>) escribió: >> >>> >>> >>> On Thu, Aug 3, 2023, 23:45 DrGo <salah.mah...@gmail.com> wrote: >>> >>>> @Miguel Angel Rivera Notararigo >>>> >>>> Thanks for taking the time to write... >>>> >>>> In my proposal, people are free to add as much context as they want... >>>> >>> >>> Yeah I know, I like your proposal, it is just how they handle errors in >>> the V programming language, although they use the keyword "or" and have >>> Options/Results. >>> >>> but as a demonstration, I am using the example from >>>> Ross Cox's paper on error handling that is used by all error handling >>>> proposals to show case their approach. I do not think Ross will >>>> take your criticism personally :) >>>> >>> >>> I know, but just because he wrote that, doesn't mean it is the perfect >>> example. If I find myself writing code like that, I would probably hate >>> Go's error handling too, but that might be said for any other feature of >>> the language if I write some bad looking examples. >>> >>> I don't see how he could take my opinion personally, I didn't mean to be >>> rude, I just said it is a bad example. I am not a native speaker, so my >>> apologies if I wrote something rude. >>> >>> I on the other hand take exception to your generalization re people who >>>> complain about error handling in Go. >>>> I am sure you did not make that claim without having some sort of solid >>>> research to support it. But, Go designers themselves admit that this is an >>>> issue and have written >>>> tons on it. >>>> >>> >>> You don't need a research or statistics if the complain is: "I don't >>> want to write 'if err != nil { return err }' every single time". >>> >>> It means they use "if err := w.Close(); err != nil { return err }" for >>> throwing the error, right? It is literally what they said or am I assuming? >>> >>> This same people will complain about your proposal, "I don't want to >>> write 'orelse return err' every single time", and then we will add >>> 'w.Close()!' or 'try w.Close()' to the language, and then we will be very >>> happy with our Go++ wich has 3 ways of doing the same thing. >>> >>> >>>> In one or two replies above we were discussing how error handling >>>> opinions can become religions each with its own priests who think they are >>>> the only saved faction, and that their rituals are the only right approach >>>> for all situations. >>>> >>> >>> I know, as I said, I like your proposal, but one of Go best features is >>> the lack of new features. I am arguing against my own taste, because I like >>> 'w.Close() or return fmt.Errorf("cannot close destination: %v", err)', but >>> I like more the simplicity of Go. >>> >>> >>>> Best wishes, >>>> >>>> >>>> On Thursday, August 3, 2023 at 9:07:52 PM UTC-6 Miguel Angel Rivera >>>> Notararigo wrote: >>>> >>>> func CopyFile(src, dst string) error { >>>> r, err := os.Open(src) >>>> if err != nil { >>>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>>> } >>>> defer r.Close() >>>> >>>> w, err := os.Create(dst) >>>> if err != nil { >>>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>>> } >>>> >>>> if _, err := io.Copy(w, r); err != nil { >>>> w.Close() >>>> os.Remove(dst) >>>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>>> } >>>> >>>> if err := w.Close(); err != nil { >>>> os.Remove(dst) >>>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>>> } >>>> } >>>> >>>> I think it is a bad example, how do you know where CopyFile failed? >>>> >>>> The "copy ..." part shouldn't be in there, you should add valuable >>>> context to your errors, if CopyFile fails, the caller already knows it was >>>> a copy error because the function has a big "Copy" on his name right? you >>>> should do this instead: >>>> >>>> func CopyFile(dst, src string) error { >>>> r, errOS := os.Open(src) // Avoid shadowing errors, don't use err >>>> if errOS != nil { >>>> return fmt.Errorf("cannot open source: %v", errOS) >>>> } >>>> >>>> defer r.Close() >>>> >>>> w, errCD := os.Create(dst) >>>> if errCD != nil { >>>> return fmt.Errorf("cannot create destination: %v", errCD) >>>> } >>>> >>>> defer w.Close() >>>> >>>> if _, err := io.Copy(w, r); err != nil { // Local scope error, so err >>>> is fine >>>> os.Remove(dst) >>>> return fmt.Errorf("cannot copy data from source: %v", err) >>>> >>>> } >>>> >>>> if err := w.Close(); err != nil { >>>> os.Remove(dst) >>>> return fmt.Errorf("cannot close destination", err) >>>> } >>>> } >>>> >>>> // Caller should do this. >>>> if err := CopyFile("dst.txt", "src.txt"); err != nil { >>>> // Here is where you should add 'copy' to the error message. >>>> return fmt.Errorf("cannot copy '%s' to '%s': %v", src, dst, err) >>>> } >>>> >>>> People complaining about Go's error handling regularly don't handle >>>> errors, they just throw them like exceptions. >>>> >>>> If you really hate Go's error handling, just use: >>>> >>>> func catch(err error) { >>>> if err != nil { >>>> panic(err) >>>> } >>>> >>>> // And use recover somewhere >>>> } >>>> >>>> Which is a bad practice, but at least we (the people who like how Go >>>> handle errors) can still handle our errors without any language change. >>>> >>>> On Tue, Aug 1, 2023, 13:06 DrGo wrote: >>>> >>>> Thanks. >>>> The keystroke saving is not the motivation. The aim is to reduce the >>>> code reader’s mental load. My approach allows for clearer code where the >>>> main program logic is not dwarfed by the error handling code while >>>> maintaining the explicitly of error handling and the possible error-induced >>>> interruption in program flow. It avoids creating new if scope when one is >>>> not desired and offers opportunities for further deduplication of error >>>> handling code although each error is still handled individually. Compare >>>> the following; which one would you prefer to read a lot of? >>>> >>>> - current approach; error handling to program logic ratio: 13:5 >>>> >>>> func CopyFile(src, dst string) error { >>>> r, err := os.Open(src) >>>> if err != nil { >>>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>>> } >>>> defer r.Close() >>>> >>>> w, err := os.Create(dst) >>>> if err != nil { >>>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>>> } >>>> >>>> if _, err := io.Copy(w, r); err != nil { >>>> w.Close() >>>> os.Remove(dst) >>>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>>> } >>>> >>>> if err := w.Close(); err != nil { >>>> os.Remove(dst) >>>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>>> } >>>> } >>>> >>>> - new approach ratio 5:5 >>>> func CopyFile(src, dst string) error { >>>> r, err := os.Open(src) *orelse* return fmt.Errorf("copy %s %s: %v", >>>> src, dst, err) >>>> defer r.Close() >>>> >>>> w, err := os.Create(dst); *orelse* return fmt.Errorf("copy %s %s: %v", >>>> src, dst, err) >>>> err := io.Copy(w, r) *orelse* { >>>> w.Close() >>>> os.Remove(dst) >>>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>>> } >>>> >>>> err := w.Close() *orelse* { >>>> os.Remove(dst) >>>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>>> } >>>> } >>>> >>>> On Sunday, July 30, 2023 at 9:27:27 PM UTC-6 Marcello H wrote: >>>> >>>> I think the current error handling is just fine. >>>> For the extra typing, they invented keyboard snippets and such. >>>> >>>> But for this proposal, I would like to see how a return with multiple >>>> values would look to get a better understanding. >>>> ``` >>>> // translate this in the proposed solution? >>>> func myFirstFunction() (string, err) { >>>> result, err := myFunction() >>>> if err != nill { >>>> return rest, err >>>> } >>>> } >>>> ``` >>>> >>>> Op maandag 31 juli 2023 om 04:32:01 UTC+2 schreef DrGo: >>>> >>>> Another possibility Jeremy is that the orelse block is executed if any >>>> of the returned error values is not nil. >>>> >>>> On Sunday, July 30, 2023 at 8:14:58 PM UTC-6 DrGo wrote: >>>> >>>> Thanks... >>>> yes indeed. Too many requirements but I think this solution comes close >>>> to meeting them. If a rare function returns more than one error value (yet >>>> to see one in the wild) then the compiler should reject orelse use and the >>>> user can fallback on the (the if err!= nil) approach. >>>> >>>> On Sunday, July 30, 2023 at 6:02:57 PM UTC-6 Jeremy French wrote: >>>> >>>> Also, errors are values, which means - although uncommon - a function >>>> could return two or more error values. Which would orelse evaluate? Even >>>> if you arbitrarily chose one, that would violate the explicit vs implicit >>>> code flow principle. >>>> >>>> My sympathies, OP. I too hate the "if err!= nil" boilerplate, and have >>>> suggested my own idea for fixing it, which was similarly dismantled for >>>> good reasons by those more knowledgeable than me. The truth is, this >>>> problem/issue has so many restrictions placed on it (currently idiomatic >>>> principles, backwards compatibility promise, explicit vs implicit, etc) >>>> that the set of possible solutions is VERY narrow, possibly infinitely so. >>>> >>>> On Sunday, July 30, 2023 at 3:51:49 PM UTC-4 Brian Candler wrote: >>>> >>>> err := io.Copy(w, r) *orelse* { >>>> w.Close() >>>> os.Remove(dst) >>>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>>> } >>>> >>>> My question still stands. Semantically, what value exactly does the >>>> "orelse" condition test is not equal to nil? >>>> >>>> - does it test the value from the preceding assignment? If so, is >>>> "orelse" only valid immediately following an assignment expression? The >>>> original posting didn't say this. And if it *is* linked to an assignment >>>> expression which assigns multiple values, does it only look at the last >>>> value? (Again, that was not specified) >>>> >>>> - does it always test a variable called "err"? The original posting >>>> said it was equivalent to "if err!=nil" but a later post contradicted this >>>> >>>> - does it test the value from the 'return' expression at the end of the >>>> block following orelse? Except in this case, it can't because it's buried >>>> inside fmt.Errorf >>>> >>>> On Sunday, 30 July 2023 at 17:55:34 UTC+1 DrGo wrote: >>>> >>>> Good point Harri, >>>> >>>> This is what the correct version will look like using this proposal >>>> >>>> func CopyFile(src, dst string) error { >>>> r, err := os.Open(src) *orelse* return fmt.Errorf("copy %s %s: %v", >>>> src, dst, err) >>>> defer r.Close() >>>> >>>> w, err := os.Create(dst); *orelse* return fmt.Errorf("copy %s %s: %v", >>>> src, dst, err) >>>> err := io.Copy(w, r) *orelse* { >>>> w.Close() >>>> os.Remove(dst) >>>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>>> } >>>> >>>> err := w.Close() *orelse* { >>>> os.Remove(dst) >>>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>>> } >>>> } >>>> >>>> In a more complex func, the error formatting/handling code can be >>>> further deduplicated by extracting it into a closure. >>>> e.g., >>>> >>>> func CopyFile(src, dst string) error { >>>> copyErr:= func(err error) { >>>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>>> } >>>> r, err := os.Open(src) *orelse* return copyErr(err) >>>> defer r.Close() >>>> >>>> w, err := os.Create(dst); *orelse* return copyErr(err) >>>> err := io.Copy(w, r) *orelse* { >>>> w.Close() >>>> os.Remove(dst) >>>> return copyErr(err) >>>> } >>>> >>>> err := w.Close() *orelse* { >>>> os.Remove(dst) >>>> return copyErr(err) >>>> } >>>> } >>>> >>>> On Sunday, July 30, 2023 at 8:17:31 AM UTC-6 Harri L wrote: >>>> >>>> IMHO, you have used the irrelevant example (== 2nd code block) from >>>> Russ Cox's paper. The paper says: >>>> > This code is not nice, not clean, not elegant, *and still wrong:* >>>> like the previous version, it does not remove dst when io.Copy or >>>> w.Close fails. >>>> >>>> I want to compare your proposal with the third example from the paper, >>>> which does (proper) error annotation and cleanup. Thanks. >>>> On Sunday, July 30, 2023 at 8:57:15 AM UTC+3 DrGo wrote: >>>> >>>> I looked at the long list of proposals to improve error handling in go >>>> but I have not seen the one I am describing below. If I missed a similar , >>>> can you pls direct me to where I can find it. If not what do you think of >>>> this approach. >>>> >>>> This involves introducing a new keyword "orelse" that is a syntactic >>>> sugar for an "if err!=nil" block. >>>> >>>> The example code in Russ Cox's paper[1] will look something like this: >>>> >>>> func CopyFile(src, dst string) error { >>>> >>>> r, err := os.Open(src) orelse return err >>>> >>>> defer r.Close() >>>> >>>> w, err := os.Create(dst) orelse return err >>>> >>>> defer w.Close() >>>> >>>> err = io.Copy(w, r) orelse return err >>>> >>>> err = w.Close() orelse return err >>>> >>>> } >>>> >>>> It is an error to not return an error from an orelse block. >>>> >>>> In my eyes, this has the same explicitness and flexibility of the >>>> current style but is significantly less verbose. It permits ignoring the >>>> error, returning it as is or wrapping it. Because orelse is not used for >>>> any other purpose, it would be easy for reviewers and linters to spot lack >>>> of error handling. >>>> >>>> It also works well with named returns. e.g., >>>> >>>> func returnsObjorErro() (obj Obj, err error) { >>>> >>>> obj, err := createObj() orelse return //returns nil and err >>>> >>>> } >>>> >>>> otherwise orelse is like "else" so e.g., it can be followed by a block >>>> if additional cleanup or error formatting etc is needed before returning, >>>> eg >>>> w, err := os.Create(dst) orelse { >>>> .... >>>> return err >>>> } >>>> >>>> Similarity to "else" hopefully means that it is easy to learn. It is >>>> obviously backward compatible >>>> >>>> What do you think? >>>> >>>> [1] >>>> https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md >>>> >>>> -- >>>> >>>> You received this message because you are subscribed to the Google >>>> Groups "golang-nuts" group. >>>> >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to golang-nuts...@googlegroups.com. >>>> To view this discussion on the web visit >>>> https://groups.google.com/d/msgid/golang-nuts/36110a8d-a26f-48be-83fd-73af755e88f4n%40googlegroups.com >>>> <https://groups.google.com/d/msgid/golang-nuts/36110a8d-a26f-48be-83fd-73af755e88f4n%40googlegroups.com?utm_medium=email&utm_source=footer> >>>> . >>>> >>>> -- >>>> You received this message because you are subscribed to the Google >>>> Groups "golang-nuts" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to golang-nuts+unsubscr...@googlegroups.com. >>>> To view this discussion on the web visit >>>> https://groups.google.com/d/msgid/golang-nuts/2c9fa4b1-e536-4743-ac20-181e550bd14fn%40googlegroups.com >>>> <https://groups.google.com/d/msgid/golang-nuts/2c9fa4b1-e536-4743-ac20-181e550bd14fn%40googlegroups.com?utm_medium=email&utm_source=footer> >>>> . >>>> >>> -- >>> You received this message because you are subscribed to a topic in the >>> Google Groups "golang-nuts" group. >>> To unsubscribe from this topic, visit >>> https://groups.google.com/d/topic/golang-nuts/dRLR4hxxI8A/unsubscribe. >>> To unsubscribe from this group and all its topics, send an email to >>> golang-nuts+unsubscr...@googlegroups.com. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/golang-nuts/CAF9DLCkTKJz8tpOwFQzV%3DoXe6R6aS-0ssnXdwDraDS112gnQ0w%40mail.gmail.com >>> <https://groups.google.com/d/msgid/golang-nuts/CAF9DLCkTKJz8tpOwFQzV%3DoXe6R6aS-0ssnXdwDraDS112gnQ0w%40mail.gmail.com?utm_medium=email&utm_source=footer> >>> . >>> >> >> >> -- >> V >> > -- V -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAPUu9svMHhF2agkci3LMJjnX9AOdVmYjtphnK07w8c_-m3ZAKg%40mail.gmail.com.