Thanks Tim for patiently explaining your perspective. Much appreciated. 
Please see my reply to Marcelo H showing using real life code  that the 
outcome goes much further than replacing the err!=  nil bit. 
On Monday, July 31, 2023 at 7:20:18 PM UTC-6 Tim Casey wrote:

>
> >> You do not think this is a significant  reduction in boilerplate?
>
> I understand people having a complaint about the verbosity of error 
> handling.  But, this follows C code error handling.  So to me, it is not 
> all *that* bad.  
> I think the measurable reduction in boilerplate code is ' ; err != nil' 
> for ' orelse '.   And I do not believe this is worth a keyword.  Some of 
> the context is  being used to C.  And another aspect is being used to perl 
> and its one liners.  With perl, the debugger is not something which is 
> close to gdb/adb or the like.  So the comparison is not about saving code.
>
> I would suggest, if I had a bold idea (and probably dumb), to have a 
> functional way to handle this.   Something like:
>
>     HandleErrorChain( todoList []func() (TYPE,error), errorHandler func () 
> TYPE, error ) (TYPE, error)
>
> Which means, I have a list of things I want to do and I want the error 
> handling to be all the same for all of them.  Then the *chain* of things 
> would make sense with a single handler.  This has the expense of being 
> kinda odd so at the very least it would need idiomatic polishing.  I also 
> think I am too ignorant to have a real say in any of this.
>
> >> Why it won't work with one time retires? That is like one time retires 
> won't work in an if-else block
>
> I think there is a bit of talking past each other here.  Or at least I 
> dont understand.  I think orelse is too specific to be helpful.  That is, 
> it is too precise to reduce a large swath of what might look like error 
> handling code, because error handling code can at times be specific.  The 
> first dumb example I came up with is a simple one-time retry, which I have 
> put in code at times.  It is usually ugly, but effective:
>
>     v,err := dosomething()
>     if err != nil {
>         v,err = dosomething()
>     }
>     if err != nil {
>         handleError(err)
>    }
>    importantOperation(v)
>
> This with the token:
>
>     if v,err := dosomething() orelse {
>         v,err = dosomething() orelse {
>             handleError()
>         }
>     }
>     importantOperation(v)
>
> The savings is the two 'err != nil' lines.
>
> If I take a step back, some of what I am reacting to is how much it is 
> discussed.  It *feels*, at least to me as an ignorant person in this 
> context, as if people were not handling errors previously.  Golang is 
> forcing this now and the resulting lines of code look like 'too much' 
> compared to previous lines of code.  But I think this is a direct design 
> goal.  If the keyword vs lines of code/tokenspace is worth it, so be it.  
> Who am I to say.  If we are truely circling on a way to handle errors in a 
> chain, then the chain aspect is at least as important as any one line, and 
> up to this point has largely been ignored.
>
> In any event, i dont mean to be argumentative or even contrarian.  Sorry 
> if it comes across that way.
>
> tim
>
>
> On Mon, Jul 31, 2023 at 4:46 PM DrGo <salah....@gmail.com> wrote:
>
>> Thanks for the valuable feedback,
>> The verbosity of error handling is the number one concern for Go 
>> developers in the most recent survey. So there is a need for doing 
>> something about it.. except that there are many possibly conflicting 
>> requirements outlined by the Go team. 
>> The problem with the abbreviated if err!= nil in your example:
>>   if x,err := something() ; err != nil {
>>         handleErrorAndReturn
>>     }
>> is that x is local to the if scope and often that won't work forcing the 
>> more verbose:
>>    x,err := something()
>>   if err != nil {
>>         handleErrorAndReturn
>>     } 
>> If you have few of those as is the case in io programs; there is real 
>> impact on the readability of the code.
>> the oresle approach avoids that problem (the x stays in the scope of the 
>> func).
>>
>>    x,err := something() orelse {
>>         handleErrorAndReturn
>>     } 
>> You do not think this is a significant  reduction in boilerplate? The 
>> only thing that will do a better job is a try-catch which is not acceptable 
>> to the Go team (fortunately). 
>>
>> why the line-by-line would break with orelse? they are working fine with 
>> the one-liner you cited:
>>   if x,err := something() ; err != nil 
>>
>> Why it won't work with one time retires? That is like one time retires 
>> won't work in an if-else block.
>>
>> Thanks again,
>>
>> On Monday, July 31, 2023 at 3:59:50 PM UTC-6 Tim Casey wrote:
>>
>>>
>>>
>>> I do not think this reduces boilerplate code.  This compacts it, which 
>>> is different.
>>>
>>> I think any one-liner-return-on-err makes the language harder to debug.  
>>> It is very common breakpoints are set for exceptional cases, which tend to 
>>> be surprising.  If the test and the return are on the same line then all of 
>>> the line-by-line tools will break down, at least a little bit.
>>>
>>> If you see:
>>>     x,err := something() ; err != nil {
>>>         handleErrorAndReturn
>>>     }
>>>
>>> At the very least, the template will not work for things like one time 
>>> retries, if error do something else, log the error and 
>>> DoSomethingAdditional().  This would be a sub scope and in golang i would 
>>> expect this to have '{}' as part of the scope shift.  If this is 
>>> acceptable, then you are very likely to be on a separate line in any 
>>> event.  So the original looks like:
>>>
>>>   err := io.Copy(w, r) *orelse* {
>>> DoSomethingElse()
>>> }
>>>
>>> This means the only 'boilerplate' is 'orelse' <- '; err != nil', which 
>>> seems rather expensive for this error handling.
>>>
>>> As a slight change of subject, I find the whole discussion about 
>>> 'saving' boilerplate to be well over-stated, too much work and energy (at 
>>> least by me as an outside observer).  Having something which fits within 
>>> the design of the language, making it a developer centric language, would 
>>> seem to fight with any one-line-template approach.
>>>
>>> tim
>>>
>>>
>>>
>>>
>>>
>>> The test and the handle all fit on one line.   I dont think having a 
>>> single line return, like perl 'next if STATEMENT' style fits within golang 
>>> language goals.
>>>
>>> On Mon, Jul 31, 2023 at 8:18 AM DrGo <salah....@gmail.com> wrote:
>>>
>>>> Me too but I do not have high hopes
>>>>
>>>>
>>>> On Monday, July 31, 2023 at 12:10:24 AM UTC-6 Mark wrote:
>>>>
>>>>> Given that this proposal is to reduce boilerplate, and assuming the 
>>>>> semantic issues could be solved, it seems to me that the 'return' is 
>>>>> redundant (i.e., could be implicit) and that 'orelse' could be done with 
>>>>> the existing 'else' keyword, i.e.,
>>>>>
>>>>> ```
>>>>> result, err := someCall() else rest, err
>>>>> ```
>>>>> Anyway, I really do hope the long-winded error syntax gets solved 
>>>>> somehow!
>>>>>
>>>>> On Monday, July 31, 2023 at 5:41:49 AM UTC+1 DrGo wrote:
>>>>>
>>>>>> func myFirstFunction() (string, err) {
>>>>>>
>>>>>>    result, err := myFunction() orelse return rest, 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/b87365af-9a72-4f8d-ad0b-1ee69cc1ad35n%40googlegroups.com
>>>>  
>>>> <https://groups.google.com/d/msgid/golang-nuts/b87365af-9a72-4f8d-ad0b-1ee69cc1ad35n%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...@googlegroups.com.
>>
> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/golang-nuts/9453a6fe-04c2-4c6d-88e9-4ec1cbd59361n%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/golang-nuts/9453a6fe-04c2-4c6d-88e9-4ec1cbd59361n%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/14b505e9-9061-4a55-a309-69536dffcd85n%40googlegroups.com.

Reply via email to