Discussing implementations of the (returns..., error) idiom from golang in 
other languages, I noted a common thing: non-go developers often 
conceptualized this as a back channel and didn't intuit that it's just a 
return-value convention.

This lead me to a new idea for addressing the excess verbosity of the 
majority of trivial error handling in golang,
that is primarily just an additional reflection tag for functions and a 
mechanism to leverage that from calling
sites.

The error slot, written `error<-`.

As a return type, it is just the type `error` but tags the function as 
having return field N be recognized as the error slot.
```
func ReadFile1(filename string) ([]byte, bool, error)
// *can* optionally be written
func ReadFile2(filename string) ([]byte, bool, error<-)
```

- Actual type is just 'error',
- One per function,
- Position doesn't matter,
- Named/anoymous,
- reflection gains a method that gives -1 for no error slot otherwise >= 0 
denoting which return field is official error slot,
- parsing: very context-specific cases, potentially even a dedicated 
token/symbol,

Beyond syntax support, this requires no compatibility breaking changes, but 
one such break IS proposed:

- Failing to forward/capture the error slot of a method in a function 
without an error slot be a compile error,

```
// slotted
func AnError() error<- { return io.EOF }

// old code, unslotted
func OldError() error { return io.EOF }

// old code, unslotted
func OldFunction() error  {
  OldError()  // valid as currently

  AnError()   // compile error suggesting `_ = AnError()`

  _ = AnError()  // valid but vet warned

  return AnError()  // valid
}
```

Second, a change to provide an implicit nil-or-return shorthand: replace 
the field's capture on the left side with "error<-".

```
func Old() (int, error, bool, error)    // Who knows
func New() (int, error<-, bool, error)  // They have their reasons

func Caller() (err error<-) {               // Must be slotted to use new 
syntax.
  // Old code is still absolutely valid.
  if i, e1, b, e2 := Old(); e1 != nil {
    return e1
  }

  // Also still absolutely valid.
  if i, e1, b, e2 := New(); e1 != nil {
    return e2
  }

  // Because Old doesn't specify which is a slot, we can use either:
  _, error<-, _, _ = Old()
  // aka: if _, err, _, _ = Old(); err != nil { return }

  _, _, _, error<- = Old()
  // aka: if _, _, _, err = Old(); err != nil { return }

  // Slotted functions are constrained to the error slot return tho.
  _, error<-, _, _ = New()  // valid
  // _, _, _, error<- = New()  // invalid, slot mismatch
}
```

A final benefit of marking your function slotted is that if you fail to 
capture a call slot yourself, it introduces an implicit panic

```
func Panicy() error<- {
  Old()   // no change
  New()   // if new's error slot != nil, panics. vet warning.
}
```

Some of the people I discussed this with immediately went to method 
chaining, but I think the above change actually already
brings that approach to a more beautiful middle ground:


A couple folks asked me about chaining: Special-case a method returning one 
value and an error slot:

```
func OpenFile(name string) (*File, error<-)
func (f *File) ReadRaw() (*RawStuff, error<-)
func (r *RawStuff) Decode() (*Data, error<-)

// Old Style
func StructFromFile1(name string) (data *Data, err error) {
  var file  *File
  var raw   *RawStuff

  file, err = OpenFile(name)
  if err == nil {
    raw, err = file.ReadRaw()
    if err == nil {
      data, err = raw.Decode()
    }
  }

  return
}

// Rusty, too terse and prone to creating hard to decipher multi-part 
mega-statements.
func StructFromFile2(name string) (*Data, error<-) {
  return OpenFile(name).ReadRaw().Decode()
}

// A properly go-beautiful style:
func StructFromFile3(name string) (*Data, error<-) {
  file, error<- := OpenFile(name)
  raw, error<- := file.ReadRaw()
  return raw.Decode()
}
```

-- 
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/2025acf5-a7d0-48be-8a29-d9ed717a7566n%40googlegroups.com.

Reply via email to