Ari
Ari

Reputation: 6199

Mimicking Pythons list comprehension in Go over a range of numbers

In Python I can do something like:

numbers = [i for i in range(5)]

Which will result in:

>> [0, 1, 2, 3, 4]

I'm learning Go so I thought I'd try and replicate that process:

package main

import "fmt"

func inRange(num int) []int {
    // Make a slice to hold the number if int's specified
    output := make([]int, num)

    // For Loop to insert data
    for i := 0; i < num; i++ {
        output[i] = i
    }
    return output
}

func main() {
    x := inRange(10)
    fmt.Print(x)
}

Output:

>> [0, 1, 2, 3, 4]

Seems pretty verbose, is there a simpler way you could achieve this in Go? I also like in python I can make it a bit more complex

evens = [i for i in range(10) if i % 2 == 0]
>> [0, 2, 4, 5, 8]

This question isn't so much how to make Go work like Python, I would like to know how a Go Developer would achieve the same thing native/naturally.

Upvotes: 1

Views: 1674

Answers (2)

Hymns For Disco
Hymns For Disco

Reputation: 8405

I think the natural way to do it in Go is to just consider things on a case-by-case basis. The cases that make Python's list comprehensions look really appealing are when you are trying to something very basic, like populating an array with ascending numbers. If its such an easy concept, we should be able to write it simply. You may disagree here, but I would say that allocating a list of ascending numbers (or even numbers) is really not a typical problem and doesn't seem to have much purpose.

The trap with list comprehensions is that it becomes tempting to use them for more complicated scenarios. Take this example from Geeks for geeks


# 2-D List of planets 
planets = [['Mercury', 'Venus', 'Earth'], ['Mars', 'Jupiter', 'Saturn'], ['Uranus', 'Neptune', 'Pluto']] 

flatten_planets = [] 

for sublist in planets: 
    for planet in sublist: 

        if len(planet) < 6: 
            flatten_planets.append(planet) 

print(flatten_planets)

Output:

['Venus', 'Earth', 'Mars', 'Pluto']

This can also be done using nested list comprehensions which has been shown below:

# 2-D List of planets 
planets = [['Mercury', 'Venus', 'Earth'], ['Mars', 'Jupiter', 'Saturn'], ['Uranus', 'Neptune', 'Pluto']] 

# Nested List comprehension with an if condition 
flatten_planets = [planet for sublist in planets for planet in sublist if len(planet) < 6] 

print(flatten_planets) 

Output:

['Venus', 'Earth', 'Mars', 'Pluto']

Though it may be satisfying to reduce 4 lines of code down to 1, using a "comprehension" here has arguably made the code less comprehensible to humans.

This expression ...

[planet for sublist in planets for planet in sublist if len(planet) < 6]

Just seems off-putting, the same amount of "nesting" (the thing list comprehensions make go away), is happening, just now there are no visual clues like indentation to help us understand it. We have to read through this line carefully and reconstruct the nested logic in our head to know how it works.

The article I took this from explains comprehensions like this:

List Comprehensions are one of the most amazing features of Python. It is a smart and concise way of creating lists ...

This is a very python kind of attitude where when a feature makes you feel smart for using it in your code, that means that its good, even if it makes it harder for other people (or yourself at a later date) trying to read and understand your code. This kind of attitude is strongly rejected in Go.

One memorable quote on this topic from one of Go's creators, Rob Pike (I'm paraphrasing here)

People have asked us for these kinds of features, and we say "no". One of the reasons is that, if you add these features, people are going to use them, that's why they're there. But they may be more expensive than a simple for loop. They tend to generate more expensive solutions to problems that have much simpler solutions

Upvotes: 1

Volker
Volker

Reputation: 42439

[I]s there a simpler way you could achieve this in Go?

Basically no.

You can simplify your for loop a bit with range but that is it. Rule of thumb: there is no magic in Go.

Upvotes: 5

Related Questions