Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: Go 2: For Else branch #41348

Closed
snadrus opened this issue Sep 11, 2020 · 12 comments
Closed

proposal: Go 2: For Else branch #41348

snadrus opened this issue Sep 11, 2020 · 12 comments

Comments

@snadrus
Copy link

@snadrus snadrus commented Sep 11, 2020

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.

@gopherbot gopherbot added this to the Proposal milestone Sep 11, 2020
@gopherbot gopherbot added the Proposal label Sep 11, 2020
@jcorbin
Copy link

@jcorbin jcorbin commented Sep 11, 2020

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.

@fzipp
Copy link

@fzipp fzipp commented Sep 11, 2020

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

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Sep 11, 2020

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!

@bcmills
Copy link
Member

@bcmills bcmills commented Sep 14, 2020

Compare #24282

@ltto

This comment was marked as off-topic.

@go101
Copy link

@go101 go101 commented Sep 15, 2020

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?

[edit]: a better example for the occasion:

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

// vs.

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

@deanveloper deanveloper commented Sep 21, 2020

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.

@gopherbot
Copy link

@gopherbot gopherbot commented Oct 11, 2020

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.)

@gopherbot gopherbot closed this Oct 11, 2020
@snadrus
Copy link
Author

@snadrus snadrus commented Oct 19, 2020

@deanveloper
Copy link

@deanveloper deanveloper commented Oct 19, 2020

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.

@jcorbin
Copy link

@jcorbin jcorbin commented Oct 19, 2020

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

notwithstanding

@jcorbin
Copy link

@jcorbin jcorbin commented Oct 19, 2020

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
9 participants
You can’t perform that action at this time.