A complete example (followed by the code it replaced):

```
package main

import (
    "fmt"
    "os"
)

func getMotd() (string, error<-) {
    motd, error<- := os.ReadFile("/etc/motd")
    return "MOTD:\n---\n" + string(motd) + "\n---\n", nil
}

func getPwd() (string, error<-) {
    pwd, error<- := os.Getwd()
    return "PWD:\n" + pwd + "\n", nil
}

func action() error {
    motd, error<- := getMotd()
    pwd,  error<- := getPwd()

    fmt.Println(motd, pwd)

    return nil
}

func main() {
    if err := action(); err != nil {
      fmt.Printf("ERROR: %s\n", err)
    }
}
```
The Go Playground (golang.com) <https://play.golang.com/p/nk3ePQhjEWC>

or main could be lazy and let `error<-` panic when err != nil:
```
func main() {
    action()
}
```

The current go code would be:

```
package main

import (
    "fmt"
    "os"
)

func getMotd() (string, error) {
    motd, err := os.ReadFile("/etc/motd")
    if err != nil {
        return "", err
    }
    return "MOTD:\n---\n" + string(motd) + "\n---\n", nil
}

func getPwd() (string, error) {
    pwd, err := os.Getwd()
    if err != nil {
        return "", err
    }
    return "PWD:\n" + pwd + "\n", nil
}

func action() error {
    motd, err := getMotd()
    if err != nil {
        return err
    }
    pwd,  err := getPwd()
    if err != nil {
        return err
    }

    fmt.Println(motd, pwd)

    return nil
}

func main() {
    if err := action(); err != nil {
      fmt.Printf("ERROR: %s\n", err)
    }
}
```
https://play.golang.com/p/2_pk-FNv-dk
On Tuesday, December 27, 2022 at 3:52:41 PM UTC-8 Oliver Smith wrote:

> 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/36564865-4624-4dc4-89fe-ad509b033108n%40googlegroups.com.

Reply via email to