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

New slices are relevant #80

Closed
sonatard opened this issue Apr 24, 2020 · 2 comments
Closed

New slices are relevant #80

sonatard opened this issue Apr 24, 2020 · 2 comments

Comments

@sonatard
Copy link

sonatard commented Apr 24, 2020

It is warned by the wsl if I declare a new slice before the range loop.
I expect it's not warned.

only one cuddle assignment allowed before range statement (wsl)

https://play.golang.org/p/VEpWPSRTNfj

func evenFilter(a*A) []int{
	slice := a.slice
	newSlice := make([]int, 0, len(slice))
	for _, v := range slice { /* only one cuddle assignment allowed before range statement (wsl) */

		if v % 2 == 0 {
			newSlice = append(newSlice, v)
		}
	}

	return newSlice
}

The following codes are uncomfortable.

func evenFilter(a*A) []int{
	newSlice := make([]int, 0, len(a.slice))

	for _, v := range a.slice {

		if v % 2 == 0 {
			newSlice = append(newSlice, v)
		}
	}

	return newSlice
}
func evenFilter(a*A) []int{
	slice := a.slice
	newSlice := make([]int, 0, len(slice))

	for _, v := range slice {

		if v % 2 == 0 {
			newSlice = append(newSlice, v)
		}
	}

	return newSlice
}
@bombsimon
Copy link
Owner

Thanks for the issue!

It's interesting that you say this because I think what you ended up with in your second example is more or less exactly what my intentions was with this linter, to end up with code like that. To me it reads like this:

  • Create variables to use throughout the scope, a new slice
  • Iterate over something, in this case the passed argument
  • Return the new slice

The first example you have is the one with most questions about. For reference, it's discussed at least in #33 and #71. In addition to what's said in #71 I can add that the reason for this is that each block should be seen as its own operation and could potentially even be its own function. Consider functional languages such as Haskell or Elixir, they don't even have for loops but instead you would use a fold or a recursive function.

The only thing that I can think of that would support alternative solutions and is yet on the wish list is to allow to cuddle variables that are used anywhere in the block (but still as long as only one is cuddled). See #24 and #50. If those were to be implemented and set to true, this would be an alternative.

func evenFilter(a*A) []int{
	newSlice := make([]int, 0, len(a.slice))
	for _, v := range a.slice {
		if v % 2 == 0 {
			newSlice = append(newSlice, v)
		}
	}

	return newSlice
}

And this, although I don't see why one would assign a separate variable to only used it in len like that.

func evenFilter(a*A) []int{
	slice := a.slice

	newSlice := make([]int, 0, len(slice))
	for _, v := range slice {
		if v % 2 == 0 {
			newSlice = append(newSlice, v)
		}
	}

	return newSlice
}

So to sum it up, there will not be support to cuddle multiple statements before blocks because it's one of the core ideas to have each block separated. Although the possibility to cuddle variables above a block that's used somewhere within

@sonatard
Copy link
Author

Thank you for your thoughtful commentary!
I understand your design and philosophy, looking forward to solve #24 and #50.

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

No branches or pull requests

2 participants