Great suggestion 
f := os.Open("filename.ext")
else err != nil {
    log.Fatal(err)
}

is much needed syntax improvement vs the current syntax. 

I would further suggest f ?= os.os.Open("filename.ext") : log.fatal("Cant 
open filename.ext") 
But the GO 'custodians' get apoplexy whenever they see any syntax that 
resembles the C ternary operator.
Chill-out 'custodians' !! 
'?' is just a symbol that can be replaced by some another one 
On Saturday, February 15, 2020 at 6:06:39 PM UTC-5, teknoslo wrote:
>
> This is more of a request for comments and not a complete proposal. I will try
> to keep this short(ish) and simple.
>
> Note that the `else` I will write about is not to be confused with the usual
> `else` used with `if`. It is an `else` in a slightly different context.
>
> `else` is basically an `if` with a variable initialized to the last return 
> value
> of a function call from the previous line.
>
> Note: "from the previous line" is a simplification. Between the function call
> and the `else` statement white space and comments are allowed, but nothing
> else.
>
> Another note: "function call" is also a simplification. It can be any 
> statement
> that returns a value. It could be, for example, the "comma ok" idiom used for
> testing whether an entry in a map is present.
>
> A few simple rules:
>
>    - Only the last return value is ever taken, not multiple.
>    - If there is no return value, `else` is not possible.
>    - The variable is defined only within the scope of the `else` block.
>    - The name of the variable can be any valid identifier.
>    - Braces are mandatory.
>
>
> Code like this:
>
> f, err := os.Open("filename.ext")
> if err != nil{
>     log.Fatal(err)
> }
>
> would become:
>
> f := os.Open("filename.ext")
> else err != nil {
>     log.Fatal(err)
> }
>
> The `err` variable in the example above is automatically initialized to the 
> last
> return value of the function call `os.Open`. The variable could have any valid
> variable name and is defined only in the `else` block.
>
> I like to read the example above with an implicit try before the function 
> call.
> I.e., try opening filename.ext, else if err is not nil... For this reason, I
> call this construct else catch.
>
> A longer example from Error Handling - Problem Overview 
> <https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md>:
>
> func CopyFile(src, dst string) error {
>     r, err := os.Open(src)
>     if err != nil {
>         return fmt.Errorf("copy %s %s: %v", src, dst, err)
>     }
>     defer r.Close()
>
>     w, err := os.Create(dst)
>     if err != nil {
>         return fmt.Errorf("copy %s %s: %v", src, dst, err)
>     }
>
>     if _, err := io.Copy(w, r); err != nil {
>         w.Close()
>         os.Remove(dst)
>         return fmt.Errorf("copy %s %s: %v", src, dst, err)
>     }
>
>     if err := w.Close(); err != nil {
>         os.Remove(dst)
>         return fmt.Errorf("copy %s %s: %v", src, dst, err)
>     }
> }
>
> would become:
>
> func CopyFile(src, dst string) error {
>     r := os.Open(src)
>     else err != nil {
>         return fmt.Errorf("copy %s %s: %v", src, dst, err)
>     }
>     defer r.Close()
>
>     w := os.Create(dst)
>     else err != nil {
>         return fmt.Errorf("copy %s %s: %v", src, dst, err)
>     }
>
>     io.Copy(w, r)
>     else err != nil {
>         w.Close()
>         os.Remove(dst)
>         return fmt.Errorf("copy %s %s: %v", src, dst, err)
>     }
>
>     w.Close()
>     else err != nil {
>         os.Remove(dst)
>         return fmt.Errorf("copy %s %s: %v", src, dst, err)
>     }
> }
>
> By using the else catch we declutter the function calls, more specifically
> assignments, thus improving readability. Error handling stays familiar,
> explicit, and simple.
>
> And since the variable in else catch is defined only in the `else` block, we 
> do
> not need to re-assign the `err` variable again and again, making the code more
> obvious and unambiguous.
>
> I would like to note that the else catch example is longer, but I think length
> should not be equated with readability.
>
>
>
> Else catch is not meant to replace the `if err != nil` idiom, but rather
> complement it. It would allow for a clear separation of return values we 
> "care"
> about and error handling. Or put another way, it would allow for a clear
> separation of a happy and an unhappy path of execution.
>
>
>
> What about the error handling blocks?
>
> We should not try to stash away error handling. Most gophers are already used 
> to
> skipping error handling blocks while reading Go. Using else catch would make
> that even easier. IDEs could collapse else catch blocks on command.
>
>
>
> Else catch is orthogonal and can be used for anything, not just error 
> handling.
> We just have to remember that it always takes the last (and no more) return
> value of a function call from the previous line.
>
> For example, we can test for existence of a key:
>
> m := map[string]int{
>     "route": 66,
> }
> i := m["route"]
> else !ok {
>     i = -1
> }
>
>
>
> Now, there is a slight problem with current else catch. If it is basically an
> `if`, what happens if we use multiple variables in the condition? Which 
> variable
> came from the last return value?
>
> firstTimeBonus := true
> apples := map[string]int{
>     "bob": 7,
>     ...
> }
> apples["john"]
> else !ok && firstTimeBonus {
>     apples["john"] = 3
> }
>
> In this case we can probably figure out that variable `ok` is the last return
> value of `apples["john"]`. But it is not explicitly stated that `ok` came from
> the last return value. What if `ok` variable was already declared and we
> unknowingly shadowed it? And how would the compiler know to which variable to
> assign the last return value?
>
> This could be solved by allowing only one variable in the `else` condition.
> Then the example above would be invalid, which it should be, because the if
> statement would be more appropriate. Also if there was only one variable 
> allowed
> in the condition, there would be no confusion as to where the variable came
> from.
>
>
>
> I believe something like else catch could be beneficial to Go, mainly 
> improving
> readability. But there are a few problems to consider.
>
> `else` would have different semantics depending on the context. This should 
> not
> be a problem for people, but it could be for the compiler and other tools.
>
> Go would have a new, not widely known construct. How much would it impact the
> learning curve of the language?
>
>
>
> This is just an idea and I am interested in what you think.
>
>    - Would else catch be useful to you?
>    - Could it be simpler? Maybe a keyword or a built-in that could take the 
> last return value and we could use if with a short statement instead of 
> `else`.
>    - Do you see a problem with it? Does it feel too much like magic?
>    - Is it trying to solve a problem you even have?
>    - Do the pros outweigh the cons?
>
>

-- 
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/5f7ba765-ac52-418f-96f5-f715e16baec0%40googlegroups.com.

Reply via email to