Can someone please explain the benefit of ‘error return’ over ‘checked 
exceptions’ ? I have made the point a few times and it goes to crickets - I 
have to believe that is because there is none, or it is difficult to 
communicate.

The ‘handle where they occur claim’ is weak, as you can handle exceptions at 
the call site with similar LOC and constructs - but why when in most cases (of 
non-trivial software) the error value is just returned up. No offense to 
Wojciech - the rpc transport layer doesn’t do the retires, it passes up an 
error, and a higher level performs retry logic, if all retries fail, it will 
pass up another error that the rpc failed, etc. This pattern is used throughout 
well designed software. If you hard using this pattern you are creating very 
hard to maintain software.

Checked exceptions are ‘error values’ with more information (e.g stack traces, 
causes, etc.), and can be enforced by the compiler (declared) and inspected by 
modern IDE’s for code complete. ‘error returns’ have none of these features. 
The only valid claim is that they are more expensive than error values, BUT you 
should not be using exceptions - or error values - for flow control. This is 
the fundamental problem to me with Go’s error handling - the flow control and 
errors are mixed leading to very difficult code to read & validate that all 
potential paths are handled now and in the future.



> On Feb 21, 2021, at 10:10 AM, Wojciech S. Czarnecki <o...@fairbe.org> wrote:
> 
> Dnia 2021-02-20, o godz. 16:48:09
> Michael MacInnis <michael.p.macin...@gmail.com> napisał(a):
> 
>> I can tell you most emphatically that I am not proposing not checking 
>> and/or not handling errors.
> 
> I did not stated that you won't. Cited piece was directed at "just return err"
> code stressing that it is not that common in the production code, mine's.
> 
>> I'd like to know if, for functions like the 
>> ones just mentioned, a pattern exists for "eliminating 
> 
>> much of the boilerplate that arises if every error is checked with a rote if
> 
> I said twice that for me it is not "boilerplate" but much appreciated feature
> of the language whose creators knew and acknowledged that every piece of
> code is written once by one developer but is then being read over and over
> by way more people than one.
> 
> And I have had not less emphatically told that where there is a function
> that just returns with err, even in "many places", the bytewise cost of return
> is some 30 bytes usually placed by the IDE with three strokes of mine.
> 
> For these three strokes where I just return (now):
> 
> As a reader I gained clear information that here something was checked then
> function just spilled error up *but* I have the surrounding context at sight.
> 
> As an author I gained - now or later:
> - A ready space to comment on and/or decorate the error value.
> - If I am decorating or creating error value, I am right in scope.
> - If this is recoverable failure, I can try to recover it now.
> 
>> And further if that pattern can be implemented as a library/package
>> with acceptable trade offs.
> 
> In this thread it was proven that this antipattern can be implemented
> as a library/package - using import, then setup, then a call to obscure
> function - all to replace a 26 or 30 bytes long idiom - by Michael Ellis.
> 
>> I'd like to know if, for functions like the 
>> If … a pattern exists for "eliminating [ these "ifs" ]
> 
> Yes it does exist. I once upon a time did a "fail" package and accompanying
> generator to implement such "if-less" pattern to use in a cases where cost
> of acquiring a resource is high and a bunch (say 8-10) of such resources is
> needed to complete the task. It was a waste of time, as new people need to
> be taught to read and understand it anyway. So it was abandoned due to
> onboarding issues. It really was not worth the time.
> 
> ``` go
> for fail.With(err) { // bind an error type variable,
>    s, abort := fail.Simple() // set up a single pass loop
>    abort.Where(err != nil, !ok, z < 0) // set common "failure" condition(s)
> 
>  z := z                  // test z < 0 (a "checked assignment")
>  r, ok := <-ch           // test !ok
>  x, y, z, err := f(z, r) // test err != nil, then test z < 0
>  abort.If(x > y)         // test x > y (a "plain test")
>  x, y, err = m(x, y)     // test err != nil
>  return x, y, z, nil     // can be prepended by an optional 'pass:'
> 
> abort:
>  fmt.Printf("‖ %s: \t( %s )\n", err.Error(), s.Trig)
>  return 0, 0, 0, err
> }
> // output:
> ‖ failed Test:             ( x > y )       // for x > y
> ‖ failed Assignment: ( !ok )          // for closed ch
> ‖ failed Assignment: ( z < 0 )       // for z < 0
> ‖ Whatever err said: ( err != nil )  // for failed f(z, r) and m(x, y)
> ```
> 
> Early iteration (live example) to be seen here: 
> https://play.golang.org/p/W35BVsZnZ-q
> 
> Hope this helps,
> 
> -- 
> Wojciech S. Czarnecki
> << ^oo^ >> OHIR-RIPE
> 
> -- 
> 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/20210221171014.2c247c6d%40xmint.

-- 
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/CE33E8B3-B7CF-44E7-8078-742ADB8676F4%40ix.netcom.com.

Reply via email to