Go: proposal: Go 2: For Else branch

Created on 11 Sep 2020  ·  12Comments  ·  Source: golang/go

Whenever a Golang program needs to determine a property of all of a set/list/map/chan, it requires an "if" branch operation on a "found" variable at the end of a loop. Ex:

var found bool
for _, v := haystack {
    if v == needle {
      found = true
      break
    }
}
if !found {  
  // Operation when the set lacks the item
}

With a For-Else construct, this could save a variable, a branch, 3 lines, and has good readability:

for _, v := range haystack {
   if v == needle {
      break
   }
} else {
  // Operation when the set lacks the item   
}

The assembly would be as simple as having break jump to a label below where the end of the For loop jumps to.

Go's overloaded For construct could allow this with Range and it can work with a condition. It has no interesting meaning for unconditional looping. This idea is borrowed from Python.

Go2 LanguageChange Proposal WaitingForInfo

Most helpful comment

Why not write a contains function, or wait for generics and write a generic contains function?

All 12 comments

Fwiw, such a construct is possible today without the bool or resorting to assembly:

    for _, v := range haystack {
        if v == needle {
            goto next
        }
    }
    // Operation when the set lacks the item

next:
    // either way, we continue here

This sort of Pythonic for/else syntax would merely by sugar.

Why not write a contains function, or wait for generics and write a generic contains function?

For language change proposals, please fill out the template at https://go.googlesource.com/proposal/+/refs/heads/master/go2-language-changes.md .

When you are done, please reply to the issue with @gopherbot please remove label WaitingForInfo.

Thanks!

Compare #24282

想你们这样 猫猫狗狗的需求都提到issues GO2会越来越臃肿的
现在也没有什么不好的啊

I often find I need the following else for form instead:

if len(values) == 0 {
   ... // print some info
} else for _, v := range values {
   ...
}

Surely, currently we can write it as

if len(values) == 0 {
   ... // print some info
}

for _, v := range values {
   ...
}

But I think the former is more logical (and could be a bit more efficient).

If if-block can follow else, why can't others?

if vs := f(); len(vs) == 0 {
} else {
  for _, v := range vs {
  }
}

// vs.

if vs := f(); len(vs) == 0 {
} else for _, v := range vs {
}

I'm personally just not a fan of for else in python. It's very useful, but it just doesn't read well in my opinion and is often a bit confusing.

Timed out in state WaitingForInfo. Closing.

(I am just a bot, though. Please speak up if this is a mistake or you have the requested information.)

For followers, the GOTO approach works:
https://play.golang.org/p/8ha8Spl4vBG

So there's no need for "isFound" variables nor the setting or checking of
them.

On Sun, Oct 11, 2020 at 3:17 PM GopherBot notifications@github.com wrote:

Closed #41348 https://github.com/golang/go/issues/41348.


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/golang/go/issues/41348#event-3864000391, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AAOU4LTY3KHQJRTMAOMI5MTSKIAGBANCNFSM4RIBYJRA
.

While that works in that specific example, the general case is a bit more complicated: https://play.golang.org/p/wMaykOGCfMC

The code requires 2 gotos which cross over each other, which can quickly lead to spaghetti code if there is more code in each section other than a simple fmt.Println. If code blocks and indents were used, it would look a lot better (which is the case for for-else). I however think that for-else doesn't look very good and isn't super intuitive. Maybe there is another word which could be used (fallthrough?), as the concept of for-else is very nice, however it just doesn't seem to lead to readable code. Maybe an entirely new concept could be thought up. Or we could just use a found variable for more complicated cases.

Maybe there is another word which could be used (fallthrough?)

notwithstanding

Looking back at this thread, I'm not sure if anyone's pointed out the precedent of text/template's {{ range }} ... {{ else }} ... {{ end }} ; so there it is fwiw

Was this page helpful?
0 / 5 - 0 ratings