YAEHI (Yet another error-handling idea)

183 views
Skip to first unread message

Andrey Tcherepanov

unread,
Jun 29, 2019, 9:56:09 PM6/29/19
to golang-nuts
Hello mighty fighters of errors!

Here comes my half-thought idea of another way to express error handling:

Add a postfix '?' that checks value for emptiness (nil, 0, "") AND an error for nil. 

(Denis have shred it to pieces already in https://github.com/golang/go/issues/32852. Thank you Denis.)

I am not good with expressing my inner talk, so there are couple examples

original , Go 1 function

func stat(filename string) (os.FileInfo, error) {

var info os.FileInfo
{
var a1 *os.File
if a1, err := os.Open(filename); err != nil || a1 == nil {
return _, err
}
var a2 os.FileInfo
if a2, err := a1.Stat(); err != nil || a2 == nil {
return _, err
}
info = a2
}
        return info, nil
}


And with "?", trying to avoid original try() proposal handle leak

// would return _, err, but since there is no err in signature, will return default value in case of error
// uses ? on func call that returns (value, error)
func stat2(filename string) (os.FileInfo) { file := os.Open(filename)? defer file.Close() return file.Stat()? }
// would return error too, uses ? as "not nil" on a variable too func stat3(filename string) (_ os.FileInfo, err error) {
var file *os.File
defer file?.Close() file := os.Open(filename)? return file.Stat() }

Thoughts?

Michael Jones

unread,
Jun 29, 2019, 11:05:44 PM6/29/19
to Andrey Tcherepanov, golang-nuts
My personal thought, though it may seem strange, is that the best argument for it lies in the single word sentence at the bottom of your email. You write "Thoughts?" -- and that is very expressive in English in just the way that you mean above in your examples. I don't know enough other languages to really know if the parallels are universal, but it's pretty clear to me what it means why "file?.close()" and "os.Open(filename)?" are "punctuated" as they are -- where the question is. I feel like you're asking this compiler, "is there anything about this value that you need to tell me?" I like that.

The long (crazy long!) discussion of error handling has among its many branches an analysis from the Go team about '?' and this kind of postfix interrogation. I'm watching it all with a bit of wonder, but I wanted to speak up and say how your human-language phrasing matches your idea of computer-language phrasing. That seems a powerful kind of naturalness to take advantage of in this issue and future ones.

--
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/b7520ffe-ec38-4157-8f95-92844dcb0d0f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--
Michael T. Jones
michae...@gmail.com

mh cbon

unread,
Jun 30, 2019, 9:12:18 AM6/30/19
to golang-nuts
f := file.Open() ? error {
//f is nill
return erors.Wrap("nop",err)
}
defer f.Close()

Andrey Tcherepanov

unread,
Jul 1, 2019, 5:45:13 AM7/1/19
to golang-nuts
I think it is no different from regular "if err != nil {}" handling, sorry

My thought behind ? is to make is working for a simple cases. If you are doing an error translation/transform/wrapping - this is a case that I feel is better handled by existing explicit "if err != nil" construct.

A.

Andrey Tcherepanov

unread,
Jul 1, 2019, 5:55:04 AM7/1/19
to golang-nuts
Thank you Michael.

I honestly never looked at it from a human-language prospective! Maybe because 25+ years of interacting with programming languages made me a bit deaf to the sound of it, and my head is kind of translating it back and forth transparently. To think of it, it might explain why I find sometimes it is easier to express ideas in code than a just plain old English... *sigh*

Andrey
To unsubscribe from this group and stop receiving emails from it, send an email to golan...@googlegroups.com.

Liam

unread,
Jul 1, 2019, 8:49:09 AM7/1/19
to golang-nuts
I've noted in several places that a 'try' expression (via keyword, built-in, or symbol) is suitable only when the function is expected to always succeed, and so would panic on error.

Also the symbol, which I agree is preferable, works best this way will?(always?(work?())) vs will(always(work()?)?)?
To unsubscribe from this group and stop receiving emails from it, send an email to golan...@googlegroups.com.

Andrey Tcherepanov

unread,
Jul 2, 2019, 5:42:33 AM7/2/19
to golang-nuts
Thanks Liam,

your suggested placement would make it somehow impossible (or at least I cannot see it right now) to use with someExpression?.someMember
If I am not mistaken, yours is close to the currently proposed "try", just replacing it with ?, am I right on that ?

A.

Liam Breck

unread,
Jul 2, 2019, 6:10:20 AM7/2/19
to Andrey Tcherepanov, golang-nuts
Erm, what expression besides a function call would yield an error only sometimes? I suppose channel receive, but is that a useful case?

It's all moot anyway.

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/-lmobOi3p5s/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/93987580-3f1d-4ab8-b796-2e095d49a3b4%40googlegroups.com.

Andrey Tcherepanov

unread,
Jul 2, 2019, 7:33:01 AM7/2/19
to golang-nuts
As sad as it sounds, inside of me I agree on "it is all moot anyway", but... Aren't we allowed to at least freely day-dream anyway :) ? 

I was thinking about it over weekend, and came with these "rules", but I need help on these for sure

  1. If expression ends with ? (like func()?) , then it works as return in "if a, err := func(); err != nil { return a, err }"
  2. If it is in the middle of expression ...
    1. without error handled

      val := func()?.somethingElse().member

      then it just expanded to a 

      val := (type(member))nil
      if tmp, err := func(); tmp == nil || err != nil {
          val = tmp.somethingElse().member
      }

      just saving the embarrassment of nil pointer dereference.

    2. with an error on the left side

      val, err := func()?.somethingElse()

      then it is expanded to 

      val := (type(somethingElse())nil
      var err error
      if tmp, err := func(); if err == nil && tmp != nil {
          val, err = tmp.somethingElse()
      }
         
  3. If error manipulation required - use a regular "if err != nil { return _, wrap(err, "bad thing happen") }   
I am probably overthinking it at this point (and it is way past bedtime), but maybe it might make sense to have 2 different constructs - one for nil-guard "?" and one for "check for nil AND error", thus becoming "??" 
With that logic above, the following should make some sense

type Mood interface {
    frolic()
    avoided() Mood
    passed() (Mood, error)
}

func getMood() (Mood, error) {...}

func usage1() (Mood, error) {
   return getMood()??.passed()
}

func usage2() error {
   return getMood()??.passed()
}

func usage3() interface{} {
    return getMood()?.avoided()
}

func usage4() (interface{}, error) {
    mood := getMood()??   /// will short-circuit if getMood() returns an error
    return mood?.passed() // guard for mood == nil; but will return no error in that case either since it will be nil
}

Andrey

To unsubscribe from this group and all its topics, send an email to golan...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages